是什么? 简单的来说就是对象a的属性中引用了对象b,对象b的属性中引用了对象c……最后引用到a。
1 2 3 4 5 6 7 8 9 10 11 <bean id ="a" class ="com.zmm.test.A" lazy-init ="false" > <property name ="b" ref ="b" /> </bean > <bean id ="b" class ="com.zmm.test.B" lazy-init ="false" > <property name ="c" ref ="c" /> </bean > <bean id ="c" class ="com.zmm.test.C" lazy-init ="false" > <property name ="a" ref ="a" /> </bean >
Spring是如何解决的? 1. 三级缓存(其实二级缓存也能解决,只是看是否使用AOP) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 private final Map<String, Object> singletonObjects = new ConcurrentHashMap <>(256 );private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap <>(16 );private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap <>(16 );
2.提前暴露 AbstractAutowireCapableBeanFactory类的doCreateBean()方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 protected Object doCreateBean (String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { boolean earlySingletonExposure = (mbd.isSingleton() && this .allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isTraceEnabled()) { logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references" ); } addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false ); if (earlySingletonReference != null ) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this .allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet <>(dependentBeans.length); for (String dependentBean : dependentBeans) { if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } } } } return exposedObject; }
BeanDefinitionValueResolver类下的resolveValueIfNecessary()方法
1 2 3 4 5 6 7 8 9 10 11 public Object resolveValueIfNecessary (Object argName, @Nullable Object value) { if (value instanceof RuntimeBeanReference) { RuntimeBeanReference ref = (RuntimeBeanReference) value; return resolveReference(argName, ref); } }
大致流程
源码分析 A引用B、B引用C、C引用A。根据上面大致流程来。在docreate()方法中,先对a实例化
将a实例的引用暴露 出去
准备去填充属性,进入populateBean()方法,applyPropertyValues()方法继续进入,重点来了,resolveValueIfNecessary()方法
继续进入,我们会看到会调用resolveReference()这个方法
最终又会调用**getBean()**方法
接下来我就省略对b的实例化,直接去看对c的。
继续跟着上面的走,在BeanDefinitionValueResolver类的resolveReference()方法时,调用getBean()去获取了a的实例
从缓存中获取a的实例
我们继续跟进到c实例的doGetBean()方法
这时候,c的实例化初始化已经完成了,然后就是b的初始化以及a的初始化了,步骤类似,自行去debug吧。
细节 1、在三级缓存中,实例的变更情况。例如a、b、c。序号代表顺序
一级缓存:7.添加c、9.添加b、11.添加a
二级缓存:4.添加a、10.移除a
三级缓存:1.添加a、2.添加b、3.添加c、5.移除a、6.移除c、8.移除b
2、关于构造器注入和set注入,下面是官网的解释