一. 明确需要搞清楚的问题
- 普通bean的非循环依赖bean生命周期的流程
- aop代理bean的非循环依赖的bean生命周期的流程
- 普通bean的循环依赖bean生命周期的流程
- aop代理bean的循环依赖bean生命周期的流程
搞清楚四个问题, 再回答spring的bean的循环依赖, 易如反掌
循序渐进的理解也便于对比, 容易理解
二. 普通bean的非循环依赖bean生命周期的流程
1. 获取bean
AbstractApplicationContext#getBean(“a”, A.class)
AbstractBeanFactory#doGetBean(“a”, A.class)
DefaultSingletonBeanRegistry#getSingleton(“a”, true) // 尝试从缓存中获取, true表示允许提前从工厂池中获取引用, 当同一个流程中第二次调用getSingleton(“a”, true) 就会触发工厂方法中的提前引用方法, 也会触发代理判断, 所以提前引用逻辑包含了aop代理生成逻辑, 即: 提前引用不一定会生成代理, 但是提前生成代理一定需要提前引用
如果可以从缓存中获取到对象, 就不必去完成后续的实例化, 属性填充, 初始化, aop代理, 因为不管这个对象是从哪一级缓存中获取到的, 后续步骤要么已经完成(从一级缓存中获取到的),要么是该这个bean的最初一次getBean()方法的属性填充之后的再去完成初始化, 反正不应该是其他bean触发的getBean()去完成从缓存中获取的bean的后续初始化
添加到半成品池的时机
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject); // 添加到半成品池
this.singletonFactories.remove(beanName); // 从工厂池中移除
}
}
}
}
return singletonObject;
}
带createBean的getSingleton方法
// AbstractBeanFactory#doGetBean("a", A.class)
sharedInstance = getSingleton(beanName, () -> { // ObjectFactory.getObject()
try {
return createBean(beanName, mbd, args);
}
}
2. 实例化
AbstractAutowireCapableBeanFactory#doCreateBean
AbstractAutowireCapableBeanFactory#createBeanInstance: 创建实例
添加单例工厂池
创建实例只有,属性填充之前, 将提前应用的工厂方法放入工厂池中的
if (earlySingletonExposure) {
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// **添加单例工厂池**
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory); // 添加到工程池
this.earlySingletonObjects.remove(beanName); // 半成品池中移除
this.registeredSingletons.add(beanName); // 注册单例beanName的容器中
}
}
}
AbstractAutowireCapableBeanFactory#populateBean: 属性填充
AbstractAutowireCapableBeanFactory#initializeBean:初始化
try {
populateBean(beanName, mbd, instanceWrapper); // 属性填充, 循环依赖的关键点
exposedObject = initializeBean(beanName, exposedObject, mbd); // 初始化
}
3. 属性填充
AbstractAutowireCapableBeanFactory#populateBean: 属性填充
注解形式的属性填充
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// javaconfig配置的属性填充代码
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
xml形式的属性填充入口
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);// xml配置的属性填充代码
}
4. 初始化
AbstractAutowireCapableBeanFactory#initializeBean:初始化
AbstractAutowireCapableBeanFactory#invokeAwareMethods: Aware接口调用
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName); // beanName
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); // ClassLoader
}
}
if (bean instanceof BeanFactoryAware) { // beanFactory
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
BeanPostProcessor#postProcessBeforeInitialization: 调用初始化之前的后置处理器
在任何 bean 初始化回调(如 InitializingBean 的afterPropertiesSet或自定义 init 方法)之前将此BeanPostProcessor应用于给定的新 bean 实例
AbstractAutowireCapableBeanFactory#invokeInitMethods: 初始化方法
InitializingBean 的afterPropertiesSet或自定义 init 方法(@PostConstructor或者xml配置中的init-method)
先调用InitializingBean.afterPropertiesSet再调用自定义的初始化方法
BeanPostProcessor#postProcessAfterInitialization: 调用出初始化之后的后置处理器
在任何 bean 初始化回调(如 InitializingBean 的afterPropertiesSet或自定义 init 方法)之后,将此BeanPostProcessor应用于给定的新 bean 实例
AbstractAutoProxyCreator#postProcessAfterInitialization: 处理aop实现的方法
this.earlyProxyReferences.remove(cacheKey) != bean // 如果已经被提前引用, 就会返回相同的bean实例, 然后不在重复生成代理
5. 注册一次性bean的销毁方法
AbstractBeanFactory#registerDisposableBeanIfNecessary
注册到一次性bean的容器中, 注册destroy方法
public void registerDisposableBean(String beanName, DisposableBean bean) {
synchronized (this.disposableBeans) {
this.disposableBeans.put(beanName, bean);
}
}
添加到单例池的时机
DefaultSingletonBeanRegistry#addSingleton
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName); // 从工厂池中移除
this.earlySingletonObjects.remove(beanName); // 从半成品池中移除
this.registeredSingletons.add(beanName); // 注册单例beanName, Set集合, 因为在反复调用, 所以必须是Set集合
}
}
此场景是没有bean进入过半成品池中
三. aop代理bean的非循环依赖的bean生命周期的流程
- 获取bean
- 实例化
- 属性填充
- 初始化
- 注册一次性bean的销毁方法
只有初始化时候调用初始化之后的后置处理器的过程不一样, 其他流程和"普通非循环bean声明中期一样", 初始化之后的后置处理器需要为其生成aop代理, 返回代理, 最后直接放入单例池中
此场景是没有bean进入过半成品池中
四. 普通bean的循环依赖bean生命周期的流程
整体流程和普通bean生命周期也大同小异, 不同点在属性填充会触发其他bean的getBean操作
-
获取bean a(getBean(a))
-
实例化a
-
a属性填充
-
触发getBean(b)
-
实例化b
-
b属性填充
触发getBean(a): 此时工厂池命中, 返回普通的bean实例,完成填充
-
b初始化
-
b注册一次性bean的销毁方法
-
-
a初始化
-
a注册一次性bean的销毁方法
此场景是普通bean进入过半成品池中
五. aop代理bean的循环依赖bean生命周期的流程
和普通bean循环依赖场景类似, 不同点在, 工厂池中的工厂方法提前生成了aop代理, 初始化之后就不用再次生成代理了
-
获取bean a(getBean(a))
-
实例化a
-
a属性填充
-
触发getBean(b)
-
实例化b
-
b属性填充
触发getBean(a): 此时工厂池命中, 返回aop代理的bean实例,完成填充
-
b初始化
但是b实例还是在**“初始化之后的后置处理器”**生成aop代理了, 因为b不是发生循环的那一次getBean, 不会命中工厂池
-
b注册一次性bean的销毁方法
-
-
a初始化
**“初始化之后的后置处理器”**不会再生成aop代理了
-
a注册一次性bean的销毁方法
此场景是代理bean进入过半成品池中
六. 三级缓存的作用
总结下三级缓存添加移除的时机
获取bean时候: 添加半成品池的时机 (只有出现循环依赖时候, 工厂bean中有工厂方法时候才会触发)
创建实例之后, 填充属性之前: 添加工厂池的时机, 每一个需要实例化的bean都会执行这段逻辑
初始化和一次性bean销毁方法注册完成之后: 添加单例池的时机, bean实例是方法返回的, 所以直接移除半成品池和工厂池
所以我们bean引用会在池子中存在的情况如下

所以我们知道, bean实例的引用一定会进入工厂池, 最终放入单例池, 出现循环依赖才会进入半成品池
三级缓存的作用
单例池作用: 解决获取不完整bean的
半成品池作用: 解决循环依赖和避免aop代理的多次执行
工厂池作用: 创建实例本生时候, 不用关心自己是否有被循环引用, 是否有被代理(考虑是否有没有被代理的前提是循环引用).如果出现循环依赖, 生成代理工作交给出现循环依赖的时候再处理, 这样就能过保证在一个场景下的什么周期的逻辑一致性
在一个bean第一次被getBean时候, 她的执行流程总是这样的
获取bean>实例化bean>bean的属性填充>初始化bean>初始化之后的后置处理器: 如果还没有生成代理, 需要aop的bean,为其生成代理>注册单例bean的销毁方法
另外工厂池中放入的是方法不是bean实例, 所以也必须单独使用一个缓存