Spring的循环依赖

循环依赖有两种方式:构造函数参数循环依赖,以及属性循环依赖,构造函数参数循环依赖是没有办法解决的,所以我们常说的Spring解决的循环依赖一般指的是属性循环依赖。

Spring的循环依赖是通过建立三级缓存实现的三级缓存主要是为了解决在AOP情况下,出现循环依赖的问题,当然,其中的一级+二级是为了解决读取不完整的性能问题,如果没了三级缓存,使用二级缓存也能够实现功能,但是会在每次创建Bean的时候调用动态代理的判断逻辑,影响性能问题。

1
2
3
4
5
6
7
8
9
10
11
//一级缓存,单例池,用于存储已经初始化完成的Bean实例(完整品)
/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

//二级缓存,单例池,读取到不完整的Bean性能更高,用于存储未彻底完成初始化的bean实例(半成品)
/** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

//三级缓存,用于存储创建Bean的匿名内部类对象<ObjectFactory>,解决创建动态代理逻辑性能,解耦 bean动态代理问题
/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Component
public class A {
@Autowired
public B b;

public B getB() {
return b;
}

public void setB(B b) {
this.b = b;
}

public int div(int i, int j) {
System.out.println("MathCalculator...div...");
return i / j;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
@Service
public class B {
@Autowired
private A a;

public A getA() {
return a;
}

public void setA(A a) {
this.a = a;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Aspect
@Component
public class LogAspects {

// 抽取公共的切入点表达式
// 1、本类引用
// 2、其他的切面引用
@Pointcut("execution(public int spring.cricle.A.*(..))")
public void pointCut() {
}

// @Before在目标方法之前切入;切入点表达式(指定在哪个方法切入)
@Before("pointCut()")
public void logStart(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
System.out.println("" + joinPoint.getSignature().getName() + "运行。。。@Before:参数列表是:{" + Arrays.asList(args) + "}");
}
}
1
2
3
4
5
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("spring.cricle")
public class Config {
}
1
2
3
4
5
6
7
@Test
public void test02() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
A a = context.getBean(A.class);
System.out.println(a.div(1, 2));
context.close();
}

可以看到上面的A.java类和B.java类是属性循环依赖的关系,并且A类被AOP代理了,接下来分析一下怎么循环依赖的问题。

分析

摘取部分创建Bean的源码上分析:

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 <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {

String beanName = transformedBeanName(name);
Object bean;

// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
/* 省略部分代码 */
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

else {
/* 省略部分代码 */


if (!typeCheckOnly) {
//1.标记当前bean处于正在创建状态
markBeanAsCreated(beanName);
}

try {
//创建bean实例
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

/* 省略部分代码 */
}

catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
/* 省略部分代码 */
}
return (T) bean;
}
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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
//1.从缓存中获取bean实例
Object singletonObject = this.singletonObjects.get(beanName);
//2.如果bean实例不存在缓存中
if (singletonObject == null) {
/* 省略部分源码 */
try {
//3.将调用函数式接口() -> { return createBean(beanName, mbd, args);}
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
/* 省略部分源码 */
}

if (newSingleton) {
//4.将初始化完成的bean添加到一级缓存中
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
1
2
3
4
5
6
7
8
9
10
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//将初始化好的bean添加到一级缓存中
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
//添加bean实例到注册列表中
this.registeredSingletons.add(beanName);
}
}
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
//doCreateBean创建A类的Bean部分伪代码
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
/* 省略部分代码 */
if (instanceWrapper == null) {
//1.实例化A对象,开辟内存空间
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
/* 省略部分代码 */

// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 2.实例化完成后,判断是否需要提前暴露该对象,结果为true
// 满足条件:单例、开启允许循环依赖的配置、并且该Bean处于正在创建状态
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");
}
//3.添加Bean的工厂对象到三级缓存中
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

// Initialize the bean instance.
Object exposedObject = bean;
try {
//4.给A的属性赋值(也就是属性B)
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
/* 省略部分代码 */
}

if (earlySingletonExposure) {
//5.从二级缓存中获取对象,并比较,下文再分析它
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
/* 省略部分代码 */
}
}

/* 省略部分代码 */
return exposedObject;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* Add the given singleton factory for building the specified singleton
* if necessary.
* <p>To be called for eager registration of singletons, e.g. to be able to
* resolve circular references.
* @param beanName the name of the bean
* @param singletonFactory the factory for the singleton object
*/
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
//把singletonFactory匿名内部类添加到三级缓存中
//匿名内部类:【() -> getEarlyBeanReference(beanName, mbd, bean)】
this.singletonFactories.put(beanName, singletonFactory);
//如果二级缓存中存在该bean,则移除
this.earlySingletonObjects.remove(beanName);
//添加该bean到注册工厂中
this.registeredSingletons.add(beanName);
}
}
}

所以在给Bean对象开辟内存空间,完成实例化之后,就会将该Bean对象存放在三级缓存singletonFactories中。

然后才调用populateBean方法

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
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
/* 省略部分代码 */
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//根据【@Autowired】的实现类【AbstractAutowireCapableBeanFactory】
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//通过调用它的postProcessProperties获取属性B
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;
}
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}

if (pvs != null) {
//给Bean(A)的赋值属性B
applyPropertyValues(beanName, mbd, bw, pvs);
}
}

通过跟踪上文AbstractAutowireCapableBeanFactory.postProcessProperties()方法,想要给A类赋予B属性,就需要先创建B对象,最终它会调用来创建B对象。

1
2
3
4
5
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
throws BeansException {
//beanName:B类
return beanFactory.getBean(beanName);
}

B类的创建Bean实例的逻辑和A类相同,因为B类也需要调用populateBean给属性A赋值,在给A赋值的过程中,最终会重新回到上文中的resolveCandidate调用beanFactory.getBean()获取A对象的实例,接着进一步分析调用getBean()-doGetBean()的方法。

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
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {

String beanName = transformedBeanName(name);
Object bean;
//1.获取Bean的缓存(其中包括从一级、二级、三级缓存中获取)
//2.由于之前已经创建过A实例并存在第三缓存中,所以这里能够返回一个A对象
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

/* 省略部分代码 */
}
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
//allowEarlyReference参数默认为true
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
//1.先从一级缓存中获取对象,若存在则返回
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//2.若对象不存在,则从二级缓存中查找该对象
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock

singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
//3.若对象不存在一级、二级缓存中时,并且存在于三级缓存中时
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//4.调用工厂对象的getObject()方法【() -> getEarlyBeanReference(beanName, mbd, bean)】
// 提前,实际上是调用了【AnnotationAwareAspectJAutoProxyCreator】
// 最终返回一个动态代理对象Proxy
singletonObject = singletonFactory.getObject();
//将该动态代理对象存放到二级缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
//把该bean的函数接口从三级缓存中移除
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//获取初始化B类的属性A的实例
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//动态代理的【AnnotationAwareAspectJAutoProxyCreator】将在这里调用
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
//返回被AOP代理的A类的Proxy对象
return exposedObject;
}
1
2
3
4
5
6
7
8
9
//AnnotationAwareAspectJAutoProxyCreator.getEarlyBeanReference
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
//把对象加入到AOP处理的缓存集合中
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
//最终还是调用了AOP动态代理包装原对象,并返回
return wrapIfNecessary(bean, beanName, cacheKey);
}

所以在这时候,就能够返回一个A类的动态代理对象,是在初始化B类,给B类开辟实例空间后,准备赋值属性A时,调用beanFactory.getBean(A)时创建的。

当给B类的初始化成功后,最终会调用addSingleton()方法,添加到一级缓存中,然后调用链将回到初始化实例的函数上,B的初始化是由于初始化A时,需要赋值A的属性B,才会被调度的。

这时候,当A初始化完成后,doCreateBean()方法的第五步:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if (earlySingletonExposure) {
//这时候从二级缓存中获取的bean实例,是一个动态代理对象proxy
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
//bean对象是一个原生实例,它是被createBeanInstance()创建出来的
//exposedObject是一个原生实例,因为在初始化B时已经调用了AOP的动态代理创建过一次proxy对象
//所以原生Bean再次调用BeanPostProcessor.postProcessAfterInitialization,AOP内部有缓存不会再创建对象
//所以这个逻辑【exposedObject == bean】在生成AOP动态代理时为true
//所以初始化A成功之后,会将对外暴露的实例(原生)替换成动态代理对象
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
/* 省略部分代码 */
}
}

总结:

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
getBean(A)
-> doGetBean(A)
#判断A对象是否存在缓存中
-> getSingleton(A)
#标记A对象正在被创建
-> markBeanAsCreated(A)
-> getSingleton(beanName, ObjectFactory<?>)
-> ObjectFactory.createBean()
-> doCreateBean(A)
-> createBeanInstance()
#添加bean相关的【getEarlyBeanReference】函数接口到三级缓存中
-> addSingletonFactory(beanName, singletonObject)
-> populateBean()
#给A对象属性赋值时调用getBean创建B类的实例
-> getBean(B)
-> doGetBean(B)
-> markBeanAsCreated(B)
-> getSingleton(beanName, ObjectFactory<?>)
-> createBean()
-> doCreateBean(B)
-> createBeanInstance()
-> addSingletonFactory(beanName, singletonObject)
-> populateBean()
#给B对象属性赋值时调用getBean创建A类实例
-> getBean(A)
-> doGetBean(A)
#尝试从缓存中获取A对象,并将(proxy)A对象存放在二级缓存中
-> getSingleton(A)
#从三级缓存中调用特殊的BeanPostProcessor
-> ObjectFactory.getEarlyBeanReference
#AbstractAutoProxyCreator,创建动态代理对象
-> getEarlyBeanReference
#将原对象包装成动态代理对象
-> wrapIfNecessary(A)
#返回动态代理对象A
-> return proxyA
#通过反射把A对象赋值到B对象的属性中
-> applyPropertyValues()
#将初始化B存放在一级缓存中
-> addSinleton(B)
#通过反射把B对象赋值到A对象的属性中
-> applyPropertyValues()
#从二级缓存中获取proxyA
-> getSingleton(beanName, false);
# exposedObject和bean都是原生A对象,二级缓存中的是proxyA
-> if (exposedObject == bean) { exposeObject = proxyA}
#添加动态代理对象到一级缓存中
-> addSingleton(proxyA)

在没有添加动态代理的情况下,使用二级缓存就能解决循环依赖的问题,其调度过程如下图:

circular-01


“本篇文章主要摘自参考资料

最后更新: 2020年10月19日 14:02

原始链接: https://midkuro.gitee.io/2020/10/24/spring-circularReferences/

× 请我吃糖~
打赏二维码