举个简单的例子
A 依赖 B,B 又依赖 A,它们之间形成了循环依赖。
或者是 A 依赖 B,B 依赖 C,C 又依赖 A,同样的 也是循环依赖
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"); } }
import javax.annotation.PostConstruct; @Component public class B { @Autowired private A a ; @PostConstruct public void init(){ System.out.println("A"); } }
【测试代码】
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; } }
【运行结果】
分析下原因