首页 > 编程语言 > 详细

spring-ioc的极简实现

时间:2021-05-05 21:51:36      阅读:31      评论:0      收藏:0      [点我收藏+]

简介

spring ioc的极简实现,可以完成自动属性注入,使用二级缓存解决循环依赖(就是把半成品对象放个map里先保存着),基于注解,可以指定配置文件,总计不到100行代码,可以简单对spring依赖注入有个大致的了解,项目下载链接在文末

大概步骤

最基本的注解

Autowired注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}

Component注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
}

ComponentScan注解(这个注解其实也可以不要,比如默认就扫描main方法目录)

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ComponentScan {
    String value();
}

Application类

用来解析配置文件,创建bean

public class Application {
    Map<Class<?>,Object> singletonInstance =new HashMap<>();
    Map<Class<?>,Object> earlySingletonInstance=new HashMap<>();
    Set<Class<?>> classSet=new HashSet<>();
    public Application(Class<?> configClass) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        //获得扫描路径
        String path = configClass.getDeclaredAnnotation(ComponentScan.class).value();
        ClassLoader classLoader = Application.class.getClassLoader();
        //获得扫描路径下所有文件
        for (File file : new File(classLoader.getResource(path.replace(".","/")).getFile()).listFiles()) {
            //这里没有递归处理,只扫描第一层的class文件
            if(!file.getName().endsWith(".class"))continue;
            String fullName=(path+"."+file.getName()).replace(".class","");
            Class<?> aClass = classLoader.loadClass(fullName);
            //保存所有被Component注解的类
            if(aClass.isAnnotationPresent(Component.class))classSet.add(aClass);
        }
        //生成半成品对象放到二级缓存
        for (Class<?> aClass : classSet) earlySingletonInstance.put(aClass,aClass.newInstance());
        //Autowired属性注入
        for (Class<?> aClass : classSet){
            Object instance = earlySingletonInstance.get(aClass);
            for (Field field : aClass.getDeclaredFields()) {
                if(field.isAnnotationPresent(Autowired.class)){
                    field.setAccessible(true);
                    field.set(instance,earlySingletonInstance.get(field.getType()));
                }
            }
            //放到单例池
            singletonInstance.put(aClass, instance);
        }
    }
    //按类型获取,生成的都是单例bean
    public <T> T getBean(Class<T> clazz){
        return clazz.cast(singletonInstance.get(clazz));
    }
}

测试

Calculate.java,Service.java这两个文件位于io.spring.test目录下

@Component
public class Calculate {
    @Autowired
    private Service service;

    public int add(int x,int y){
        return service.add(x, y);
    }
}
@Component
public class  Service {
    @Autowired
    Calculate calculate;//测试循环依赖
    public int add(int x, int y) {
        return x+y;
    }
}
@ComponentScan("io.spring.test")//扫描路径
public class App {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        Application appContext = new Application(App.class);//初始化
        Calculate cal = appContext.getBean(Calculate.class);//获得bean对象
        System.out.println(cal.add(3,5));
    }
}

测试程序输出8,说明依赖注入的目的达到了

项目下载

https://github.com/fuchengshun/simple-spring-ioc

spring-ioc的极简实现

原文:https://www.cnblogs.com/fuchengshun/p/14732279.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!