什么是循环依赖
举个简单的例子
A 依赖 B,B 又依赖 A,它们之间形成了循环依赖。
或者是 A 依赖 B,B 依赖 C,C 又依赖 A,同样的 也是循环依赖
模拟循环依赖的问题
代码语言:javascript复制package com.artisan.cycleDepend;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class A {
@Autowired
private B b;
@PostConstruct
public void init(){
System.out.println("A");
}
}
代码语言:javascript复制import javax.annotation.PostConstruct;
@Component
public class B {
@Autowired
private A a ;
@PostConstruct
public void init(){
System.out.println("A");
}
}
【测试代码】
代码语言:javascript复制package com.artisan.cycleDepend;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 模拟循环依赖的问题
*/
public class CycleDependTest {
private static Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
// 一级缓存
private static Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
// 模拟Spring 的 解析对象为 BeanDefinition 并放到 BeanDefinitionMap中
RootBeanDefinition a = new RootBeanDefinition(A.class);
RootBeanDefinition b = new RootBeanDefinition(B.class);
beanDefinitionMap.put("a",a);
beanDefinitionMap.put("b",b);
// 模拟Spring 的 getBean 循环创建Bean
for (String beanName : beanDefinitionMap.keySet()){
getBean(beanName);
}
}
public static Object getBean(String beanName) throws IllegalAccessException, InstantiationException {
// 实例化
RootBeanDefinition beanDefinition = (RootBeanDefinition) beanDefinitionMap.get(beanName);
Class<?> beanClass = beanDefinition.getBeanClass();
Object o = beanClass.newInstance();
// 属性填充
// 获取声明的字段
Field[] declaredFields = o.getClass().getDeclaredFields();
// 遍历
for (Field declaredField : declaredFields) {
// 检查是否有Autowired注解
Autowired annotation = declaredField.getAnnotation(Autowired.class);
if (annotation != null){
// private属性 需要设置为true
declaredField.setAccessible(true);
// 获取属性的名字
String name = declaredField.getName();
// 递归调用getBean获取实例
Object bean = getBean(name);
// 字段设置属性
declaredField.set(o,bean);
}
}
// 初始化 init-method 。。。。
// 存入一级缓存
singletonObjects.put(beanName,o);
return o;
}
}
【运行结果】
分析下原因