github地址: github.com/zexho994/IO…
解决循环依赖
在spring中使用“3级缓存”来解决循环依赖问题,不要纠结spring为何要使用3个map来实现,抛开实现的细节,从问题原因着手,这个问题其实使用很好理解。
何为循环依赖?
下面的A和B就互相依赖彼此,这样就会有一个问题,在创建A的时候需要创建B,但是创建B的时候又需要创建A,看起来像是一个先有鸡还是蛋的问题。
@Bean
public class ClassA {
@Autowired
public ClassB ib;
}
@Bean
public class ClassB {
@Autowired
public ClassA ia;
}
但是要知道Bean的创建其实是分为多个步骤的,就好理解了。
graph LR
n0(start) --> n1(创建instance) --> n2(填充需要注入的fields字段) --> n3(end)
在创建完instance后,里面的字段其实都还是null的,例如已经创建ClassA实例a,和ClassB实例b,此时a.ib = null和b.ia = null. 然后赋值 a.ib = b 和 b.ia = a,这之后,a和b中的字段都赋值完了,且都是完整可用的对象了。
public Object getBean(String beanName) {
BeanDefinition bean = this.getBeanInstance(beanName);
if (!bean.isInit()) {
try {
this.initBean(bean);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return bean.getInstance();
}
// 初始化bean
private void initBean(BeanDefinition beanDefinition) throws IllegalAccessException {
Object instance = beanDefinition.getInstance(); // 获取bean的isntance
beanDefinition.setStatusInitialized(); //设置为已初始化
this.initAutowire(instance);
}
// 遍历所有字段,为有@Authwired注解的实现注入
private void initAutowire(Object instance) throws IllegalAccessException {
Field[] fields = instance.getClass().getFields();
for (Field field : fields) {
if (field.getDeclaredAnnotationsByType(Autowired.class).length == 0) {
continue;
}
Class<?> fieldType = field.getType();
Object bean = this.getBean(fieldType.getSimpleName());
field.set(instance, bean); //field赋值
}
}
有一个比较好的类比,leetcode的一道算法题two sum leetcode-cn.com/problems/tw…,其中一种题解就是遍历一边,存储所有值和索引到map中,然后遍历一次map,每次判断是否有要的数。
这个也是,先讲instance存到map中,然后把map中instance的fields都进行填充,就可以了。