0%

Spring循环依赖(下)

Spring循环依赖(下)

​ 上文中把springbean的创建过程大致整理了一下,但是似乎还没有回答上文背景中提出的问题,为什么在某个方法上加了一个@Async注解之后,导致出现了循环依赖报错,而上文中有两个简单小例子,其中使用了AOP,却没有出现循环依赖报错?(如果对spring中的AOP@Async实现方式有一个大概了解的话,应该知道二者都是通过生成代理对象的方式实现。)

这里举两个个例子:

  1. A对象和B对象相互依赖,且A对象中的printHelloWorld标记@Async
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Service
public class A {

@Autowired
private B b;

@Async
public void printHelloWorld(){

}
}

@Service
public class B {

@Autowired
private A a;
}


  1. A对象和B对象相互依赖,且A对象中的printHelloWorldAOP
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
@Service
public class A {

@Autowired
private B b;

public void printHelloWorld(){

}
}

@Service
public class B {

@Autowired
private A a;
}

@Slf4j
@Aspect
@Component
public class LogAspect {

@Pointcut("execution(public * cn.com.xiaocainiaoya.cyclic.A.printHelloWorld(..))")
private void testPointcut() {}

@Around("testPointcut()")
public void around(ProceedingJoinPoint point) throws Throwable {
log.info("LogAspect before");
point.proceed();
log.info("LogAspect after");
}
}

​ 在第一个例子中,在创建B对象时,B通过第三级缓存中的提前暴露对象工厂获得的A对象是A在创建过程中的空对象。当A的经过初始化之后(在initialization()方法中会执行实现了BeanPostProcessor后置处理器中的postProcessAfterInitialization方法,而@Async的实现就是AsyncAnnotationBeanPostProcessor,经过该方法后生成的代理对象为proxyA),所以就导致A对象提前暴露给B对象注入的对象与最后初始化生成的对象不一致,根据上文说的判定逻辑,最终导致循环依赖报错。

循环依赖2.png

​ 在第二个例子中,在创建B对象时,B通过第三级缓存中的提前暴露对象工厂获取的A对象是经过BeanPostProcessor后置处理器的一个子扩展接口SmartInstantiationAwareBeanPostProcessorgetEarlyBeanReference方法,处理之后变为代理对象proxyA,(这里通过提前暴露对象的工厂获取到的就是代理对象,也就是提前暴露的对象就是代理对象),所以进入上文的判定逻辑,正常返回。

循环依赖2-1.png

注意:二者之前的差别就是提前暴露的对象是不是代理对象。获取说是代理对象的暴露时机有所不同。那么为什么二者暴露代理对象的时机有所不同?二者都是通过BeanPostProcessor的实现进行处理,AOP实现类和@Async的实现类AnnotationAwareAspectJAutoProxyCreatorAsyncAnnotationBeanPostProcessor有一个很大的区别是前者实现了SmartInstantiationAwareBeanPostProcessor接口,在提前暴露对象工厂中,只会执行实现了这个接口的getEarlyBeanReference方法来获取提前暴露对象。

1
2
3
4
5
6
7
8
9
10
11
12
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
-------------本文结束感谢您的阅读-------------