0%

Spring 系列之从循环依赖到三级缓存

引言

本文以循环依赖为切入点,介绍一下 Spring 是如何实现 bean 创建以及如何通过三级缓存来解决循环依赖,对于 bean 的生命周期,读完本文之后也都迎刃而解。对了,本文用到的 spring-boot-starter-parent 版本为:2.5.15。

DefaultSingletonBeanRegistry

DefaultSingletonBeanRegistry 是 Spring 默认的单例 bean 注册器,也是相当重要的一个注册器,也是三级缓存的持有者。

三级缓存

1
2
3
4
5
6
7
8
9
// 一级缓存,保存着完整对象
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

// 二级缓存,保存着实例化还未进行初始化的对象
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

// 三级缓存,保存着创建 bean 的工厂对象
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

bean 实例与三级缓存

getSingleton(String beanName)

该方法是获取 bean 实例的入口方法,该方法会调用重载的 getSingleton 方法,我们注意到入参为 true,也就是允许获取早期的 bean 实例。

1
2
3
4
5
@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}

getSingleton(String beanName, boolean allowEarlyReference)

获取单例 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
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 在未加锁的情况下尝试从一级缓存中获取 bean 实例
Object singletonObject = this.singletonObjects.get(beanName);
// 只有一级缓存中不存在该 bean 以及当前 bean 处于创建中时才进行后续的处理,否则直接返回(一级缓存存在的话说明是完整的 bean 可以直接用;如果一级缓存不存在并且还未开始创建该 bean 那么走创建流程就行了,毕竟此时二级、三级缓存都为空,走逻辑也没意义)
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 先看看二级缓存是否存在
singletonObject = this.earlySingletonObjects.get(beanName);
// 如果二级缓存不存在,并且允许早期访问,那么就要加锁进行三级缓存的获取了
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
singletonObject = this.singletonObjects.get(beanName);
// 加锁之后再从一级缓存获取,如果还未 null,那么再从二级缓存获取,毕竟在加锁这段期间,可能当前 bean 已经被其线程创建好了(只要有方法调用 getBean 都会创建对应的 bean 实例)
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
// 既然二级缓存不存在,那么就尝试获取三级缓存
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 注意,三级缓存是提供的对象工厂实现,也就是说这为代理提供了钩子
singletonObject = singletonFactory.getObject();
// 通过三级缓存获取 bean 对象,将其移入到二级缓存,同时删除三级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}

addSingletonFactory

当实例实例化之后,需要各种代理对其进行包装,然后添加到三级缓存中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 其实从名字上来看,我们也知道该方法是将 bean 添加到三级缓存中
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
// 如果一级缓存中已经存在了,那么跳过
if (!this.singletonObjects.containsKey(beanName)) {
// 添加到三级缓存
this.singletonFactories.put(beanName, singletonFactory);
// 将当前 bean 从二级缓存中移除
this.earlySingletonObjects.remove(beanName);
// 登记为已注册
this.registeredSingletons.add(beanName);
}
}
}

💡 Tips

一级缓存存在的话,直接跳过三级缓存的添加;否则将其添加到三级缓存中,同时从二级缓存中移除。

测试用例

1
2
3
4
5
6
7
8
9
10
11
@Component
public class A {
@Autowired
private B b;
}

@Component
public class B {
@Autowired
private A a;
}

我们以两个最基本的类 A、B 为例开始我们的 bean 创建之路!

Bean 创建

当类添加 @Lazy 声明为懒加载时,只有当该类的对象被使用时才会出发 bean 创建,其余的 bean 在上下文刷新的时候就会根据具体情况选择创建了。用例中,即使类 A、B 没有任何字段需要注入,也会创建对应的 bean。

从调用栈可以看到 refresh() 方法通过 finishBeanFactoryInitialization() 由 bean 工厂 DefaultListableBeanFactorypreInstantiateSingletons() 方法完成非懒加载 bean 的实例创建,也就是触发 getBean() 方法。

getBean

getBean 将具体逻辑委托给 doGetBean 方法来实现。

1
2
3
4
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}

doGetBean

doGetBean 方法代码比较多,而且分支不仅多还很深。不过不要紧,我们逐步挑重点来一点一点啃。为了便于说明,假如我们的例子中先行创建的实例为 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
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
163
164
protected <T> T doGetBean(String name,@Nullable Class<T> requiredType,@Nullable Object[] args,boolean typeCheckOnly) throws BeansException {
// 如果需要那么就转换 bean 的名字,也就说如果 bean 名字由 & 开头,那么去掉其前缀(针对那些工厂 bean),本案例中 name 为 "a"、"b"
String beanName = transformedBeanName(name);
Object beanInstance;

/*
* 由于是第一次获取,那么 sharedInstance 肯定为 null(本例中 A 的获取会存在多次,我们稍后介绍)
*/
Object sharedInstance = getSingleton(beanName);

// 第一次由于 sharedInstance 为 null,所以该分支不会走,我们在后续介绍不为 null 的场景
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 + "'");
}
}
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

else {
// 开始具体的 bean 创建逻辑,如果当前 bean 是原型模式,同时当前线程已经在创建中,那么一搬是不会再次创建了,除非遇到循环依赖,那么就抛出异常(也就是说原型模式下,Spring 并不解决循环依赖问题)
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}

// 获取父级工厂
BeanFactory parentBeanFactory = getParentBeanFactory();
// 如果存在父级工厂同时查看是否包含当前的 bean 定义
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {

// 获取该 bean 的原始名字,然后根据需要添加 & 前缀
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);
}
}

// 如果本次并非是作为类型检测触发的 getBean 调用,那么将该 bean 标记为已创建(bean 工厂级缓存)
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}

StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
// 查找指定名字的 bean 定义,也就是 Spring 对该 bean 对象的详细描述
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 查看 bean 是否是抽象的,如果是那么抛出异常
checkMergedBeanDefinition(mbd, beanName, args);

// 获取当前 bean 依赖的 bean,比如通过 @DependsOn 注解显示声明依赖,那么就需要先创建这些 bean(本例中 A、B 均无任何依赖)
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 {
// 触发依赖 bean 的创建
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}

// 单例 bean(本例肯定是走这个分支了)
if (mbd.isSingleton()) {
// 调用 getSingleton 方法,并注册回调方法为 createBean
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 那么就需要获取具体的实例
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 原型 bean
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);
}
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

else {
// 其他作用域的 bean 创建
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
}
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);
}
});
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
}
catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
finally {
beanCreation.end();
}
}
// 判断实际的 bean 与类型是否匹配,然后做相应转换
return adaptBeanInstance(name, beanInstance, requiredType);
}

doGetBean 方法将具体的单例 bean 创建委托给了 AbstractAutowireCapableBeanFactory 工厂的 createBean 方法。而该方法又何时触发的呢?我们进入 getSingleton 一探究竟!

getSingleton

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
// 似曾相识的 getSingleton,只不过参数变了
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) {
// 如果单例工厂已经启用自毁模式了,就不要再创建 bean 了
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 不能处于排除名单中,将当前 bean 标记为创建中状态
beforeSingletonCreation(beanName);
boolean newSingleton = false;
// 是否需要记录抑制的异常
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
// 集合为空就创建新的集合
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 这里会回调 `AbstractAutowireCapableBeanFactory` 工厂的 `createBean` 方法完成对象创建
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// 思考下此时出现的场景?
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;
}
// 将 bean 从创建中状态中移除
afterSingletonCreation(beanName);
}
// 如果新的实例创建完毕,那么添加到一级缓存
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}

具体的 bean 创建又委托给了 AbstractAutowireCapableBeanFactory 工厂的 createBean 方法,当对象创建后会通过 addSingleton 方法添加到缓存中,不过我们先看创建流程!

createBean

createBean 是 AbstractAutowireCapableBeanFactory 的核心方法,用于 bean 的创建,不过从名字你也可以看的出来,它肯定还有个 doCreateBean 方法。

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
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {

if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;

// 解析除该 bean 所属的类(本例中就是 A.class、B.class 的全限定名)
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}

try {
// 用来处理当前 bean 中的方法重写
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}

try {
// BeanPostProcessors 可以从这个阶段直接生成代理对象以取代实际的 bean(当然,事务相关的代理肯定不从这个阶段生成)
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}

try {
// 继续委托给 doCreateBean 方法
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}

doCreateBean

可以看到,走到这里还没开始创建 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
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {

// bean 的包装器,持有真正的 bean 对象
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// 从缓存中删除,如果不存在就得创建了
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 此时真正的 bean 对象就创建完成并保存在 instanceWrapper 中
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 具体的 bean 实例对象(也就是本例中的 A 或者 B)
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 {
// 这里允许你对 bean 定义进行处理
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.
// 以下就是解决循环依赖的关键缓存了,从注解中我们可以看出,哪怕是类似 BeanFactoryAware 生命周期接口触发的都不在话下
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");
}
// 将当前对象由 getEarlyBeanReference 包装并存入三级缓存
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

// Initialize the bean instance.
Object exposedObject = bean;
try {
// 启用属性填充,这里就要完成依赖注入了,我们稍后详细介绍
populateBean(beanName, mbd, instanceWrapper);
// 开始初始化 bean 完成各种生命周期钩子调用,具体的我们稍后介绍
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) {
// 这里暂时不介绍(毕竟 A 的流程暂时不会走完,先走完这一步的是 B 对象,而且两者的情况还不太一样)
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 " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}


try {
// 注册 DestructionAwareBeanPostProcessors、DisposableBean interface、custom destroy method 等方法
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}

return exposedObject;
}

属性填充

自动注入就发生在当前阶段。

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
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
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 判断 bean 实例是否存在
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}

// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.

// InstantiationAwareBeanPostProcessors 接口实现回调,此时 bean 仅仅是实例化还未进行属性填充
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
// 可以指定是否进行接下来的属性填充
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}

PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 获取当前 bean 的注入方式,由于是 bean 的创建,所以这里就是 0 (不需要注入)
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 判断是否存在后置处理器
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}

for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
// 这里着重注意 AutowiredAnnotationBeanPostProcessor 处理器,由它负责自动注入
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.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) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}

自动注入实现

AutowiredAnnotationBeanPostProcessor 负责完成自动注入。

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
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 查到当前 bean 的注入元数据对象
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
// 调用注入方法
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}


public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
// 遍历需要注入的元素,回到我们的例子,因为 A 有一个注入属性 B,所以这里注入的元素就是 B;对于 B 这里注入的元素就是 A
if (!elementsToIterate.isEmpty()) {
for (InjectedElement element : elementsToIterate) {
// 由于 B 属于字段注入,这里 element 的实现为内部类:AutowiredFieldElement
element.inject(target, beanName, pvs);
}
}
}

@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
// 获取需要注入的字段,本例中 bean A 对应 B;bean B 对应 A。
Field field = (Field) this.member;
Object value;
// 第一次肯定是没有缓存的
if (this.cached) {
try {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
catch (NoSuchBeanDefinitionException ex) {
// Unexpected removal of target bean for cached argument -> re-resolve
value = resolveFieldValue(field, bean, beanName);
}
}
else {
// 主流程开始对字段 B 进行解析,这个阶段会触发 B 的构造,也就是调用 getBean() 完成 B 创建,而 B 同样有字段,所以又会回到本方法,只不过这里就要解析 B 的字段 A 了,那么又会触发 getBean 去构造 A,但是此时 A 已经处于三级缓存中了,那么就会将 A 从三级缓存中解析出来,存入二级缓存,完成 B 对象中 A 的注入。然后完成 B 对象的初始化,此时就会回到 A 的调用中来,value 就是已经初始化完成位于一级缓存中的 B,然后设置给 A。由于 A 还未初始化完成,所以 B 中的 A 由于指向了相同的引用,所以也是未初始化的。那么当字段设置完毕,就会继续 A 的初始化了,那么当 A 完成,B 中的 A 也自然是完整的对象。
value = resolveFieldValue(field, bean, beanName);
}
if (value != null) {
// 设置访问权限,然后完成设置
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}

对于 resolveFieldValue 方法,这里就不再进行展开了,感兴趣的读者可以自行查看源码,该方法会间接调用 getBean() 来完成 B 实例的构造。

总结

为了避免大家思绪混乱,我们总结一下当前发生了哪些过程:
1、getBean 方法第一调用,构造对象 A,将其包装之后存入三级缓存;
2、A 进行属性填充,发现 A 存在字段 B,而 B 也是 bean 对象,触发 B 的 getBean 调用;
3、调用 getBean 创建 B,然后将 B 进行包装存入三级缓存;
4、填充 B 的属性,发现 B 含有字段 A;
5、那么触发 A 的 getBean,完成 A 构造;

为了便于说明,我们再次回到 doGetBean 方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 此时由于 A 处于三级缓存中,那么 sharedInstance 就不会为 null
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 + "'");
}
}
// 因为 A 并非是 factoryBean,所以 beanInstance 就会直接返回完成 doGetBean 方法的调用
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

由于 getSingleton 方法已经存在 A 的实例,那么就会通过 A 对应的工厂方法拿到具体的 A 对象,然后将该实例存入二级缓存,同时从三级缓存中移除:

1
2
3
4
5
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}

那么 A 对应的工厂对象是谁呢?还记得以下代码不:

1
2
// 将当前对象由 getEarlyBeanReference 包装并存入三级缓存
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

以上代码在 deCreateBean 实例化 A 之后,会将其添加到三级缓存中,而 getEarlyBeanReference 就是 A 对应的位于 AbstractAutowireCapableBeanFactory 中的方法

1
2
3
4
5
6
7
8
9
10
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
}

getBeanPostProcessorCache().smartInstantiationAware 的实现有两个:

  • InfrastructureAdvisorAutoProxyCreator

    方法由父类 AbstractAutoProxyCreator 实现:

    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
    @Override
    public Object getEarlyBeanReference(Object bean, String beanName) {
    Object cacheKey = getCacheKey(bean.getClass(), beanName);
    // 避免重复创建代理,将该对象存入缓存进行标记
    this.earlyProxyReferences.put(cacheKey, bean);
    return wrapIfNecessary(bean, beanName, cacheKey);
    }

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    // 由于代理是在后续的 process 中创建的,所以本条件不成立
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
    return bean;
    }
    // 因为 A 并不需要代理,所以这里为 null
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
    return bean;
    }
    // 由于 A 并非 Advice、Pointcut、Advisor、AopInfrastructureBean,所以本条件也不成立
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
    }

    // 因为 A 不需要代理,所以这里也为 null
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
    this.advisedBeans.put(cacheKey, Boolean.TRUE);
    Object proxy = createProxy(
    bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
    this.proxyTypes.put(cacheKey, proxy.getClass());
    return proxy;
    }
    // 对 A 进行登记,然后返回
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
    }

    所以该方法并没有对 A 对象有任何改造。

  • AutowiredAnnotationBeanPostProcessor

    方法由父类 SmartInstantiationAwareBeanPostProcessor 实现:

    1
    2
    3
    default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
    return bean;
    }

    可以看到也只是简单的返回。

6、通过以上我们可以知道此时的 A 由于不需要代理,所以拿到的就是当初创建的 A 对象,然后将 A 从三级缓存移入到二级缓存,并注入到 B 中。其实通过循环依赖,我可能也可以看出,如果需要代理包装时,代理也并非第一次就创建出来,而是在需要用到该对象实例时,才会从三级缓冲中得到代理对象。
7、当 B 实例注入完 A 字段之后,那么就会结束 B 的属性填充阶段,接下来就是初始化阶段了。

初始化

我们继续上一阶段介绍,上一阶段中,A 对象到了属性填充阶段,而属性填充导致 B 的创建,B 的创建同样来到属性填充阶段,触发 A 的创建,当 B 完成 A 字段的注入之后也同样需要进行接下来的初始化。换而言之,A 在等待 B 的初始化完成然后再继续 A 的初始化。

initializeBean

本阶段就简单多了,主要是 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
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
// 调用各种 aware 方法,如:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware,咦?怎么没有 ApplicationContextAware 呢?
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

try {
// 调用 InitializingBean 接口实现,以及自定义的 init 方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 调用 BeanPostProcessor 的 postProcessAfterInitialization 方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

return wrappedBean;
}

💡 Tips

注意不要把 BeanPostProcessor 的 Initialization 方法与其子类 InstantiationAwareBeanPostProcessor 的 Instantiation 方法搞混哈,前者是初始化前后钩子,后者是实例化前后钩子。

还记得 doCreateBean 在初始化完成之后有个条件判断不:

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
if (earlySingletonExposure) {
// 此时 beanName 为 B,而启用早期引用为 false,也就是说只从一级二级缓存中获取实例。还记得此时缓存的状态不?A 存在于二级缓存;而 A 获取 B 时,B 处于第一次创建,所以它还在三级缓存中。所以此时获取 B 为 null; 获取 A 时得到的就是二级缓存中的实例。既然这样,B 在注册完余下的钩子之后就结束了。另外如果缓存中存在这个对象,说明存在循环依赖,那么就需要慎重处理了
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
/*
* 如果两者相等,说明在 initializeBean 阶段并没有代理产生,可以放心的返回。但是如果不想等,说明 exposedObject 被替换成了代理对象
*/
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
// 既然对象被代理了,那么就需要检查是由有其他已经创建完成的 bean 依赖了当前对象(比如说:在属性填充阶段已经为 B 填充了对象 A,但是在初始化阶段,A 被替换成了代理对象了。那么显然 B 中的 A 与实际中的 A 并不相等,那不就出问题了)
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
// 如果该对象用于实际的使用为目的,并非了类型检查,那么方法就会返回 false
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 " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// 给定的 bean 是否仅仅为了类型检查
protected boolean removeSingletonIfCreatedForTypeCheckOnly(String beanName) {
// 如果一个 bean 并非为了类型检查而创建时,会被标记为已创建状态(被添加到 alreadyCreated 集合中),如果集合不存在,说明该 bean 除了类型检查没有其他目的,那么就返回 true;如果当前集合存在,说明该 bean 是作为实际使用的,那么返回 false
if (!this.alreadyCreated.contains(beanName)) {
removeSingleton(beanName);
return true;
}
else {
return false;
}
}

一级缓存

什么时候转移至一级缓存呢?毕竟 B 当前处于三级缓存,A 处于二级缓存,接下来就介绍一级缓存的转换。

addSingleton

还记得是谁负责创建的 bean 不?doCreateBean 方法,那么谁触发的 doCreateBean 呢?是 createBean 方法,那么又是谁触发的 createBean 呢?是 getSingleton 方法通过回调来触发的。ps:是谁触发的 getSingleton 方法嘞?那还用说嘛,当然是 doGetBean 了,那么触发 doGetBean 的方法呢。。。

1
2
3
4
5
// 如果新的实例创建完毕,那么添加到一级缓存
if (newSingleton) {
addSingleton(beanName, singletonObject);
}

getSingleton 方法最后,我通过注释已经说明了,不知道大家还记得不?我们看下 addSingleton() 方法的具体实现:

1
2
3
4
5
6
7
8
9
10
11
12
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
// 将对象放到一级缓存
this.singletonObjects.put(beanName, singletonObject);
// 从三级缓存移除
this.singletonFactories.remove(beanName);
// 从二级缓存移除
this.earlySingletonObjects.remove(beanName);
// 将 bean 的名字缓存起来
this.registeredSingletons.add(beanName);
}
}

通过以上我们可以看出,A 经历了三级缓存到二级,二级到一级,B 则是直接从三级跳过了二级直接进入了一级缓存。


总结

通过本文内容,我们可以看出还有注入方式为字段注入、setter 注入解决了循环依赖。对于代理而言,并非第一次创建实例时就创建代理对象,而是放到了使用该对象时,才会从三级缓存中生成代理对象完成注入。从另一个角度我们也可以看出,三级缓存的存在其实就是为了应对动态代理,否则两级缓存就够了。


送上一张全家福