Spring循环依赖(下)
上文中把springbean
的创建过程大致整理了一下,但是似乎还没有回答上文背景中提出的问题,为什么在某个方法上加了一个@Async
注解之后,导致出现了循环依赖报错,而上文中有两个简单小例子,其中使用了AOP
,却没有出现循环依赖报错?(如果对spring
中的AOP
和@Async
实现方式有一个大概了解的话,应该知道二者都是通过生成代理对象的方式实现。)
这里举两个个例子:
- A对象和B对象相互依赖,且A对象中的
printHelloWorld
标记@Async
。
1 |
|
- A对象和B对象相互依赖,且A对象中的
printHelloWorld
被AOP
。
1 |
|
在第一个例子中,在创建B对象时,B通过第三级缓存中的提前暴露对象工厂获得的A对象是A在创建过程中的空对象。当A的经过初始化之后(在initialization()
方法中会执行实现了BeanPostProcessor
后置处理器中的postProcessAfterInitialization
方法,而@Async
的实现就是AsyncAnnotationBeanPostProcessor
,经过该方法后生成的代理对象为proxyA
),所以就导致A对象提前暴露给B对象注入的对象与最后初始化生成的对象不一致,根据上文说的判定逻辑,最终导致循环依赖报错。
在第二个例子中,在创建B对象时,B通过第三级缓存中的提前暴露对象工厂获取的A对象是经过BeanPostProcessor
后置处理器的一个子扩展接口SmartInstantiationAwareBeanPostProcessor
的getEarlyBeanReference
方法,处理之后变为代理对象proxyA
,(这里通过提前暴露对象的工厂获取到的就是代理对象,也就是提前暴露的对象就是代理对象),所以进入上文的判定逻辑,正常返回。
注意:二者之前的差别就是提前暴露的对象是不是代理对象。获取说是代理对象的暴露时机有所不同。那么为什么二者暴露代理对象的时机有所不同?二者都是通过BeanPostProcessor
的实现进行处理,AOP
实现类和@Async
的实现类AnnotationAwareAspectJAutoProxyCreator
和AsyncAnnotationBeanPostProcessor
有一个很大的区别是前者实现了SmartInstantiationAwareBeanPostProcessor
接口,在提前暴露对象工厂中,只会执行实现了这个接口的getEarlyBeanReference
方法来获取提前暴露对象。
1 | protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { |