spring-ioc的极简实现
简介
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