Spring循环依赖
1、Bean的创建和管理
创建bean的过程可简单总结为:先从单例池中获取bean,如果没有则创建并添加到单例池。
与bean工厂有关的类的继承树如下:
具体过程如下:
①Bean工厂(DefaultListableBeanFactory)调用getBean(beanName)。
1
2
3
4
5
6//AbstractApplicationContext类,实际是其子类AnnotationConfigApplicationContext类型
public Object getBean(String name) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(name);
}1
2
3
4
5//GenericApplicationContext类,实际是其子类AnnotationConfigApplicationContext类型
public final ConfigurableListableBeanFactory getBeanFactory() {
return this.beanFactory;
}1
2
3
4
5//AbstractBeanFactory类,实际是其子类DefaultListableBeanFactory类型
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}②Bean工厂(DefaultListableBeanFactory)调用doGetBean(name, null, null, false)–>getSingleton(beanName)先获取缓存中保存的单实例Bean,如果能获取到说明这个Bean之前被创建过(所有创建过的单实例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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162//AbstractBeanFactory类,实际是其子类DefaultListableBeanFactory类型
protected <T> T doGetBean(final String name, final Class<T> requiredType,
final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
//先获取缓存中保存的单实例Bean。如果能获取到说明这个Bean之前被创建过(所有创建过的单实例Bean都会被缓存起来)
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);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
//启动单实例Bean的创建流程。
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);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}③调用getSingleton(beanName, singletonFactory)进入创建bean的真正流程,创建成功后将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
54
55
56
57
58//DefaultSingletonBeanRegistry类,实际是其子类DefaultListableBeanFactory类型
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
//加锁
synchronized (this.singletonObjects) {
//双重检测
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
//标识当前bean正在创建中。
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
//通过传入的singletonFactory执行getObject()-->createBean()-->doCreateBean(),完成bean的实例化、填充属性以及初始化的流程。
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
//创建成功后添加到单例池中(一级缓存)
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}上面有个重要的步骤是当单例池中没有当前所要创建的bean时,就进入了singletonFactory.getObject()–>createBean()–>doCreateBean(),完成bean的实例化、填充属性以及初始化的流程。相关属性注入和bean初始化的逻辑已经在之前的文章写过,这里不详细说明(https://perfectcode.top/2020/12/03/Spring%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B/)。
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105//AbstractAutowireCapableBeanFactory类,实际是其子类DefaultListableBeanFactory类型
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//实例化Bean。
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
//提前暴露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");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//属性填充,里面会先执行InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()方法,如果返回false则不进行后面的属性注入操作。
//接着会执行属性自动填充(@Bean注解里的autowire())。
//最后的属性填充是通过后置处理器AutowiredAnnotationBeanPostProcessor。
populateBean(beanName, mbd, instanceWrapper);
//初始化Bean(是指根据配置自定义的初始化bean,而不是构造函数创建bean),过程为填充bean(执行实现了Aware接口方法)-->前置处理-->初始化方法-->后置处理。
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
//循环依赖检查,判断是否需要抛出异常。
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
//注册DisposableBean,如果配置了destroy-methoy,这里需要注册以便于在销毁的时候调用。
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}如果为该创建的bean开启了aop创建其动态代理对象时,在上面的initializeBean(beanName, exposedObject, mbd)对该bean的初始化逻辑中会执行到后置处理器AspectJAwareAdvisorAutoProxyCreator的postProcessAfterInitialization方法,从而继续通过调用wrapIfNecessary(bean, beanName, cacheKey)–>createProxy()方法完成此bean代理对象的创建:
1
2
3
4
5
6
7
8
9
10
11//AbstractAutoProxyCreator类,实际是其子类AspectJAwareAdvisorAutoProxyCreator类型
public Object postProcessAfterInitialization( { Object bean, String beanName)
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
图示如下:
2、解决循环依赖
Spring是通过三级缓存来解决循环依赖的,其相关定义在DefaultSingletonBeanRegistry类中:
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
26public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
//一级缓存:存放完全实例化属性赋值完成的Bean,直接可以使用。
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
//二级缓存:存放早期Bean的引用,实例化完成但尚未属性装配的Bean。
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
//三级缓存:用来保存一个对象工厂,提供一个匿名内部类,用于创建二级缓存中的对象。(存放实例化完成的Bean工厂)
//ObjectFactory为函数式接口,有且仅有一个方法,可以当做方法的参数传递进去,当指明此类型参数的方法,可以传入一个lambda表达式,在执行的时候并不会执行lambda表达式,而在调用getObject方法的是才会去调用lambda处理的逻辑。
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
}
//补充ObjectFactory接口
public interface ObjectFactory<T> {
/**
* Return an instance (possibly shared or independent)
* of the object managed by this factory.
* @return the resulting instance
* @throws BeansException in case of creation errors
*/
T getObject() throws BeansException;
}Spring中解决循环依赖重点使用到下列6个方法。
有了上面Bean的创建过程分析后,下面分析其中的有关Spring解决循环依赖的代码,代码示例如下(这里假设A依赖B,B也同时依赖A,并且需要同时创建A和B的代理对象而不是它们本身,所以也用到了AOP):
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
public class A {
B b;
public B getB() {
return b;
}
public void setB(B b) {
this.b = b;
}
}
public class B {
A a;
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
}
public class MyAspect {
public void before() {
System.out.println("前置通知...");
}
}
public class BeanTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanTest.class);
A a = (A) applicationContext.getBean("a");
System.out.println(a);
}
}(1)测试代码中执行getBean(“a”)后,来到doGetBean()–>getSingleton(beanName)方法,由于从单例池(即一级缓存singletonObjects)获取不到此bean,而且此bean(“a”)目前还未被标记为正在创建中,从而不执行synchronized代码块的内容,直接返回null。
(2)继续执行到doGetBean()的第二个getSingleton(beanName,singletonFactory)方法,此时会同时传入ObjectFactory的匿名实现类,其中重点执行了createBean()方法,此方法在getSingleton(beanName,singletonFactory)中通过singletonFactory.getObject()被间接调用。
(3)执行到createBean()–>doCreateBean()方法进入该bean(“a”)的具体创建流程。会先执行其中的createBeanInstance()创建该bean(“a”)实例。
(4)继续执行到doCreateBean()的addSingletonFactory()方法将该bean(“a”)包装成一个单例工厂加入三级缓存(singletonFactories)中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
//使用singletonobjects进行加锁,保证线程安全
synchronized (this.singletonObjects) {
//如果单例对象的高速缓存【bean名称-bean实例】没有beanName的对象
if (!this.singletonObjects.containsKey(beanName)) {
//将beanName,singletonFactory放到单例工厂的缓存(三级缓存)【bean名称-ObjectFactory】
this.singletonFactories.put(beanName, singletonFactory);
//从早期单例对象的高速缓存(二级缓存)【bean名称-bean实例】移除beanName的相关缓存对象
this.earlySingletonObjects.remove(beanName);
//将beanName添加已注册的单例集中
this.registeredSingletons.add(beanName);
}
}
}此时三个缓存的状态:
(5)当A完成了实例化并添加进了三级缓存后,开始执行doCreateBean()的populateBean()->为其进行属性注入,在注入时发现A依赖了B,那么这个时候Spring又会去执行getBean(“b”)开始了B的创建过程,其过程和上方A的创建过程相同。
(6)B的创建流程同样是getBean(“b”)–>……–>createBeanInstance(“b”),执行完后同样通过addSingletonFactory()方法将刚创建的B对象放进三级缓存中。此时三个缓存的状态:
紧接着会populateBean(“b”),在populateBean(“b”)为B注入属性的过程中发现需要注入A,所以又会通过getBean(“a”)完成A的创建流程,但由于之前被包装成单例工厂的A已经被添加到了三级缓存,于是在getBean(“a”)–>doGetBean(“a”)中第一次执行getSingleton(beanName)方法时依次检查一级、二级以及三级缓存后成功从三级缓存中获取到之前保存的被包装成单例工厂的A,并在完成singletonFactory.getObject()–>getEarlyBeanReference()后返回的对象(可能是代理对象,也可能是未经代理的原对象,但都还没有完成初始化的步骤)添加进二级缓存,同时在三级缓存中移除被包装成单例工厂的A。
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
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//从单例对象缓存中获取beanName对应的单例对象
Object singletonObject = this.singletonObjects.get(beanName);
//如果单例对象缓存中没有,并且该beanName对应的单例bean正在创建中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//如果为空,则锁定全局变量并进行处理
synchronized (this.singletonObjects) {
//从早期单例对象缓存(二级缓存)中获取单例对象(之所称成为早期单例对象,是因为earlySingletonObject里的对象的都是通过提前曝光的ObjectFactory创建出来的,还未进行属性填充等操作)
singletonObject = this.earlySingletonObjects.get(beanName);
//如果在早期单例对象缓存中也没有,并且允许创建早期单例对象引用
if (singletonObject == null && allowEarlyReference) {
//从三级缓存中根据beanName获取单例工厂
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
//如果从三级缓存中获取到单例工厂
if (singletonFactory != null) {
//如果存在单例对象工厂,则通过工厂创建一个单例对象
singletonObject = singletonFactory.getObject();
//记录在二级缓存中,二级缓存和三级缓存的对象不能同时存在
this.earlySingletonObjects.put(beanName, singletonObject);
//从三级缓存中移除
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}在上方的singletonFactory.getObject()间接调用的getEarlyBeanReference()方法到底是什么,下面看一下源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
//默认最终公开的对象是bean,通过createBeanInstance创建出来的普通对象
Object exposedObject = bean;
//mbd的systhetic属性:设置此bean定义是否是“synthetic",与AOP相关
//如果mdb不是synthetic且此工厂拥有InstantiationAwareBeanPostProcessor
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
//遍历工厂内的所有后处理器
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//如果bp是SmartInstantiationAwareBeanPostProcessor实例
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
//让exposedObject经过每个SmartInstantiationAwareBeanPostProcessor的包装
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
//返回最终经过层次包装后的对象
return exposedObject;
}发现此方法其实就是遍历所有是SmartInstantiationAwareBeanPostProcessor类型的后置处理器,然后调用它们的getEarlyBeanReference(),而在此时的符合此条件的只有通过@EnableAspectJAutoProxy注解导入的AnnotationAwareAspectJAutoProxyCreator,所以也就是调用了此后置处理器的getEarlyBeanReference(),从而调用完成后返回A的代理对象**(在不考虑AOP的情况下,这里没有对应的后置处理器可执行,相当于上面添加的工厂什么都没有干而是直接将实例化创建的普通对象返回了)**:
此时三个缓存的状态:
(8)上面的步骤执行完后,实例B成功注入了实例化完成但未完成初始化的实例A的代理对象(引用二级缓存中实例A的代理对象)。紧接着B调用doCreateBean()里的initializeBean()方法完成B的初始化工作(其中会调用后置处理器AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization()完成代理对象B的创建)。
紧接着回到了AbstractBeanFactory.doGetBean()中调用的第二个DefaultSingletonBeanRegistry.getSingleton(beanName,singletonFactory)方法,在此方法内紧接着调用addSingleton(beanName, singletonObject)方法将创建完毕的B对象添加到单例池(一级缓存中)。
1
2
3
4
5
6
7
8
9
10
11
12protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//将映射关系添加到单例对象的高速缓存中(一级缓存)
this.singletonObjects.put(beanName, singletonObject);
//移除beanName在单例工厂缓存中的数据(三级缓存)
this.singletonFactories.remove(beanName);
//移除beanName在早期单例对象的高速缓存的数据(二级缓存)
this.earlySingletonObjects.remove(beanName);
//将beanName添加到已注册的单例集中
this.registeredSingletons.add(beanName);
}
}此时三个缓存的状态:
(9)实例A在完成走完完整生命周期的B对象的属性注入后,紧接着会进行其初始化工作,而在其中也会执行调用后置处理器AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization()完成代理对象A的创建,但由于在上方代理对象B注入属性A时已经通过调用getEarlyBeanReference()完成代理A的创建并添加进AOP缓存earlyProxyReferences了,所以这里不会进入到wrapIfNecessary()的逻辑,而是直接返回bean。
(10)在实例A初始化完成后(即调用完doCreateBean()中populateBean–>initializeBean),会继续在doCreateBean()中调用getSingleton(),这一次传入的参数又不一样了,false可以理解为禁用三级缓存,前面图中已经提到过了,在为B中注入A时已经将三级缓存中的工厂A取出,并从工厂A中获取到了一个对象放入到了二级缓存中, 所以这里的这个getSingleton方法就是从二级缓存中获取到这个代理后的A对象。
最后回到了AbstractBeanFactory.doGetBean()中调用的第二个DefaultSingletonBeanRegistry.getSingleton(beanName,singletonFactory)方法,在此方法内紧接着调用addSingleton(beanName, singletonObject)方法将创建完毕的A对象移出二级缓存并加入到单例池(一级缓存中)。此时代理对象A和代理对象B终于创建完毕,循环依赖问题也解决了。
1
2
3
4
5
6
7
8
9
10
11
12protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//将映射关系添加到单例对象的高速缓存中(一级缓存)
this.singletonObjects.put(beanName, singletonObject);
//移除beanName在单例工厂缓存中的数据(三级缓存)
this.singletonFactories.remove(beanName);
//移除beanName在早期单例对象的高速缓存的数据(二级缓存)
this.earlySingletonObjects.remove(beanName);
//将beanName添加到已注册的单例集中
this.registeredSingletons.add(beanName);
}
}此时三个缓存的状态:
总结的流程图如下(参考https://hollis.blog.csdn.net/article/details/107551993):
几个疑问?
如果只有一个map,能否解决循环依赖的问题?
- 不能,如果只有一个map,那么成品对象和本成品对象必须要放在同一个map中,而半成品的对象是不能够暴露给外部使用的,所以必须要做区分,否则就有可能暴露半成品对象。
如果只有两个map,能否解决循环依赖问题?
- 能,但是有前提条件:循环依赖中不包含aop的处理逻辑。
为什么三级缓存就可以解决循环依赖中包含代理对象的问题?
- 创建代理对象前需要创建出原始对象。
- 同一个容器中不能出现同名的两个不同的对象。
如果需要代理对象,那么代理对象创建完成之后应该覆盖原始对象。
- 在getEarlyBeanReference方法中,会判断是否需要代理对象,如果创建出代理对象了,那么就需要覆盖。
在对象对外暴露的时候,如何准确的给出原始对象或者代理对象,因为正常的代理对象的创建是在BeanPostProcessor的后置处理方法中,在解决循环依赖问题的时候还没有执行到那个地方。所以此时需要lambda表达式了,类似于是一种回调机制,在确定要对外暴露的时候,就唯一性的确定到底是代理对象还是原始对象,这也是为什么不把对象直接放到二级缓存中,而通过三级缓存lambda表达式的方式来执行的原因。其实就是聊一个时间问题,什么时候需要对外暴露,程序没办法确定,所以需要通过lambda的方式,在确定需要对外暴露的时候才执行对象的确定(原始还是代理)。
在给B注入A的时候为什么要注入一个代理对象?
- 当我们对A进行了AOP代理时,说明我们希望从容器中获取到的就是A代理后的对象而不是A本身,因此把A当作依赖进行注入时也要注入它的代理对象。
A初始化的时候是对A对象本身进行初始化,而容器中以及注入到B中的都是代理对象,这样不会有问题吗?
- 不会,这是因为不管是cglib代理还是jdk动态代理生成的代理类,内部都持有一个目标类的引用,当调用代理对象的方法时,实际会去调用目标对象的方法,A完成初始化相当于代理对象自身也完成了初始化。
三级缓存为什么要使用工厂而不是直接使用引用?换而言之,为什么需要这个三级缓存,直接通过二级缓存暴露一个引用不行吗?
- 这个工厂的目的在于延迟对实例化阶段生成的对象的代理,只有真正发生循环依赖的时候,才去提前生成代理对象,否则只会创建一个工厂并将其放入到三级缓存中,但是不会去通过这个工厂去真正创建代理对象。
即使没有循环依赖,也会将其添加到三级缓存中,而且是不得不添加到三级缓存中,因为到目前为止Spring也不能确定这个Bean有没有跟别的Bean出现循环依赖。假设我们在这里直接使用二级缓存的话,那么意味着所有的Bean在这一步都要完成AOP代理,这是没有必要的。
三级缓存真的提高了效率了吗?
需要分为两点讨论:
没有进行AOP的Bean间的循环依赖:这种情况下三级缓存根本没用!所以不会存在什么提高了效率的说法。
进行了AOP的Bean间的循环依赖:假设单独创建代理对象A,而A又依赖了普通对象B。
假设使用了三级缓存的情况下,则A、B的创建流程:
假设不使用三级缓存,直接在二级缓存中,则A、B的创建流程:
上面两个流程的唯一区别在于为A对象创建代理的时机不同,在使用了三级缓存的情况下为A创建代理的时机是在B中需要注入A的时候,而不使用三级缓存的话在A实例化后就需要马上为A创建代理然后放入到二级缓存中去。对于整个A、B的创建过程而言,消耗的时间是一样的,所以不管是哪种情况,三级缓存提高了效率这种说法都是错误的。
Spring解决循环依赖的过程?
- ①在A完成实例化后,就使用实例化后的对象去创建一个对象工厂,并添加到三级缓存中,如果A被AOP代理,那么通过这个工厂获取到的就是A代理后的对象,如果A没有被AOP代理,那么这个工厂获取到的就是A实例化的对象。
- ②当A进行属性注入时,会去创建B,B首先也会被包装成一个单例工厂放进三级缓存,同时B在注入属性时又发现依赖了A,所以会去调用getBean(a)来获取需要的依赖,getBean(a)会依次从一级、二级以及三级缓存中获取,结果是从三级缓存中拿到单例工厂A,接着调用对象工厂的getObject方法来获取到对应的对象放进二级缓存,并将其注入到B中,同时删除三级缓存中的单例工厂A。
- ③紧接着B会走完它的生命周期流程,包括初始化、后置处理器等。最终B会被放到一级缓存。
- ④接着会将一级缓存中的B注入到A中后完成A的属性注入,A再完成后续初始化工作,A对象创建完成,删除二级缓存中的A,同时把A放入一级缓存。
- ⑤最后,一级缓存中保存着实例化、初始化都完成的A、B对象。