Spring创建AOP对象的时机
1.循环依赖时从三级缓存中获取早期引用对象时
三级缓存在DefaultSingletonBeanRegistry类中
singletonObjects <ConCurrentHashMap<>> 一级缓存
singletonFactories <HashMap<>> 三级缓存
earlySingletonObjects <HashMap<>> 二级缓存
首先看放入三级缓存中的是什么东西
// 放入三级缓存在AbstractAutowireCapableBeanFactory的doCreateBean方法中的下面代码
//这里就是将一个lamda表达式放到三级缓存中
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});
// 可以点进去看下getEarlyBeanReference这个方法是如何获取早期引用对象的
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
Iterator var5 = this.getBeanPostProcessors().iterator();
while(var5.hasNext()) {
BeanPostProcessor bp = (BeanPostProcessor)var5.next();
//SmartInstantiationAwareBeanPostProcessor这里会执行所有的这个接口的实现类,可以点进去看下
//实现类有哪些如下图,最关键的是AbstractAutoProxyCreator这个类,在这个类中会将原对象进行代理生成
//代理对象
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor)bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
2. Bean的后置处理器中执行AOP(BeanPostProcessor)
//核心逻辑在AbstractAutowireCapableBeanFactory类中的initializeBean这个方法的下面代码中
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
//上面代码点进去
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
Object current;
// 这里会拿到所有的后置处理器然后执行,最关键的是下图中的实现类,这些实现类就是实现Aop
//的关键地方了
for(Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {
BeanPostProcessor processor = (BeanPostProcessor)var4.next();
current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
}
return result;
}
补充: @Async注解加了之后可能就会出现循环依赖是因为,Async切面是在后置处理器中执行的,没有像其它的,比如@Transactional注解切面处理一样,在AbstractAutoProxyCreator中出现循环依赖的时候用getEarlyBeanReference方法暴露早期代理对象,导致后面注入对象的时候发现注入的对象和执行了后置处理方法后的对象不一样,然后抛出异常