二十一、创建Bean之实例化Bean对象一

创建Bean之实例化Bean对象一

createBeanInstance()方法

创建Bean实例过程的第一步:实例化Bean,方法为createBeanInstance()

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
// AbstractAutowireCapableBeanFactory.java
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 解析 bean ,将 bean 类名解析为 class 引用。
Class<?> beanClass = resolveBeanClass(mbd, beanName);

if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}

// <1> 如果存在 Supplier 回调,则使用给定的回调方法初始化策略
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}

// <2> 使用 FactoryBean 的 factory-method 来创建,支持静态工厂和实例工厂
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}

boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
// constructorArgumentLock 构造函数的常用锁
synchronized (mbd.constructorArgumentLock) {
// 如果已缓存的解析的构造函数或者工厂方法不为空,则可以利用构造函数解析
// 因为需要根据参数确认到底使用哪个构造函数,该过程比较消耗性能,所有采用缓存机制
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
// 已经解析好了,直接注入即可
if (resolved) {
if (autowireNecessary) {
// <3.1> autowire 自动注入,调用构造函数自动注入
return autowireConstructor(beanName, mbd, null, null);
}
else {
// <3.2> 使用默认构造函数构造
return instantiateBean(beanName, mbd);
}
}

// <4> 确定解析的构造函数
// 主要是检查已经注册的 SmartInstantiationAwareBeanPostProcessor
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// <4.1> 有参数情况时,创建 Bean 。先利用参数个数,类型等,确定最精确匹配的构造方法。
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}

// <4.1> 选择构造方法,创建 Bean 。
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}

// <4.2> 有参数时,又没获取到构造方法,则只能调用无参构造方法来创建实例了(兜底方法)
return instantiateBean(beanName, mbd);
}

实例化 Bean 对象,主要的逻辑为:

  • <1> 处,如果存在 Supplier 回调,则调用 obtainFromSupplier(Supplier instanceSupplier, String beanName) 方法,进行初始化。

  • <2> 处,如果存在工厂方法,则使用工厂方法进行初始化。

  • <3> 处,首先判断缓存,如果缓存中存在,即已经解析过了,则直接使用已经解析了的。根据 constructorArgumentsResolved 参数来判断:

    <3.1> 处,是使用构造函数自动注入,即调用 autowireConstructor(String beanName, RootBeanDefinition mbd, Constructor[] ctors, Object[] explicitArgs) 方法。

    <3.2> 处,还是默认构造函数,即调用 instantiateBean(final String beanName, final RootBeanDefinition mbd) 方法。

  • <4> 处,如果缓存中没有,则需要先确定到底使用哪个构造函数来完成解析工作,因为一个类有多个构造函数,每个构造函数都有不同的构造参数,所以需要根据参数来锁定构造函数并完成初始化。

    <4.1> 处,如果存在参数,则使用相应的带有参数的构造函数,即调用 autowireConstructor(String beanName, RootBeanDefinition mbd, Constructor[] ctors, Object[] explicitArgs) 方法。

    <4.2> 处,否则,使用默认构造函数,即调用 instantiateBean(final String beanName, final RootBeanDefinition mbd) 方法。

obtainFromSupplier()方法

如果存在 Supplier 回调,则使用给定的回调方法初始化策略。

1
2
3
4
5
// AbstractAutowireCapableBeanFactory.java
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}

首先,从 BeanDefinition 中获取 Supplier 对象。如果不为空,则调用 obtainFromSupplier(final String beanName, final RootBeanDefinition mbd) 方法。

Supplier

Supplier:java1.8的一个函数式接口,提供者。用于指定创建 bean 的回调。如果我们设置了这样的回调,那么其他的构造器或者工厂方法都会没有用。

1
2
3
4
@FunctionalInterface
public interface Supplier<T> {
T get();
}

如何设置Supplier参数,有对应的setter方法:

1
2
3
4
5
6
7
8
9
10
// AbstractBeanDefinition.java
/**
* 创建 Bean 的 Supplier 对象
*/
@Nullable
private Supplier<?> instanceSupplier;

public void setInstanceSupplier(@Nullable Supplier<?> instanceSupplier) {
this.instanceSupplier = instanceSupplier;
}

在构造 BeanDefinition 对象的时候,设置了 instanceSupplier 该值,(以 RootBeanDefinition 为例):

1
2
3
4
5
6
7
8
// RootBeanDefinition.java
public <T> RootBeanDefinition(@Nullable Class<T> beanClass, String scope, @Nullable Supplier<T> instanceSupplier) {
super();
setBeanClass(beanClass);
setScope(scope);
// 设置 instanceSupplier 属性
setInstanceSupplier(instanceSupplier);
}
obtainFromSupplier()方法

如果设置了 instanceSupplier 属性,则可以调用 obtainFromSupplier(Supplier instanceSupplier, String beanName) 方法,完成 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
protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
Object instance;

// 获得原创建的 Bean 的对象名
String outerBean = this.currentlyCreatedBean.get();
// 设置新的 Bean 的对象名,到 currentlyCreatedBean 中
this.currentlyCreatedBean.set(beanName);
try {
// <1> 调用 Supplier 的 get(),返回一个 Bean 对象
instance = instanceSupplier.get();
}
finally {
// 设置原创建的 Bean 的对象名,到 currentlyCreatedBean 中
if (outerBean != null) {
this.currentlyCreatedBean.set(outerBean);
}
else {
this.currentlyCreatedBean.remove();
}
}

// 未创建 Bean 对象,则创建 NullBean 对象
if (instance == null) {
instance = new NullBean();
}
// <2> 创建 BeanWrapper 对象
BeanWrapper bw = new BeanWrapperImpl(instance);
// <3> 初始化 BeanWrapper 对象
initBeanWrapper(bw);
return bw;
}

流程如下:

  • <1> 首先,调用 Supplier 的 get() 方法,获得一个 Bean 实例对象。
  • <2> 然后,根据该实例对象构造一个 BeanWrapper 对象 bw
  • <3> 最后,初始化该对象。
instantiateUsingFactoryMethod()方法

如果存在工厂方法,使用 FactoryBean 的 factory-method 来创建,支持静态工厂和实例工厂:

1
2
3
4
5
6
7
8
9
10
11
12
// AbstractAutowireCapableBeanFactory.java
// <2> 使用 FactoryBean 的 factory-method 来创建,支持静态工厂和实例工厂
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}

/**
*构造一个 ConstructorResolver 对象,然后调用其 instantiateUsingFactoryMethod(EvaluationContext context, String typeName, List<TypeDescriptor> argumentTypes) 方法。
*/
protected BeanWrapper instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}
ConstructorResolver

org.springframework.expression.ConstructorResolver 是构造方法或者工厂类初始化 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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
// ConstructorResolver.java

public BeanWrapper instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
// 构造 BeanWrapperImpl 对象
BeanWrapperImpl bw = new BeanWrapperImpl();
// 初始化 BeanWrapperImpl
// 向BeanWrapper对象中添加 ConversionService 对象和属性编辑器 PropertyEditor 对象
this.beanFactory.initBeanWrapper(bw);

// <1> 获得 factoryBean、factoryClass、isStatic、factoryBeanName 属性
Object factoryBean;
Class<?> factoryClass;
boolean isStatic;

String factoryBeanName = mbd.getFactoryBeanName();
// 工厂名不为空
if (factoryBeanName != null) {
if (factoryBeanName.equals(beanName)) {// 抛出 BeanDefinitionStoreException 异常
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"factory-bean reference points back to the same bean definition");
}
// 获取工厂实例
factoryBean = this.beanFactory.getBean(factoryBeanName);
if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {// 抛出 ImplicitlyAppearedSingletonException 异常
throw new ImplicitlyAppearedSingletonException();
}
this.beanFactory.registerDependentBean(factoryBeanName, beanName);
factoryClass = factoryBean.getClass();
isStatic = false;
}
else {
// 工厂名为空,则其可能是一个静态工厂
// 静态工厂创建bean,必须要提供工厂的全类名
if (!mbd.hasBeanClass()) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"bean definition declares neither a bean class nor a factory-bean reference");
}
factoryBean = null;
factoryClass = mbd.getBeanClass();
isStatic = true;
}

// <2> 获得 factoryMethodToUse、argsHolderToUse、argsToUse 属性
Method factoryMethodToUse = null;// 工厂方法
ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;// 参数

// <2.1> 如果指定了构造参数则直接使用
// 在调用 getBean 方法的时候指定了方法参数
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
// 没有指定,则尝试从配置文件中解析
Object[] argsToResolve = null;
// <2.2> 首先尝试从缓存中获取
synchronized (mbd.constructorArgumentLock) {
// 获取缓存中的构造函数或者工厂方法
factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
// Found a cached factory method...
// 获取缓存中的构造参数
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
// 获取缓存中的构造函数参数的包可见字段
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
// 缓存中存在,则解析存储在 BeanDefinition 中的参数
// 如给定方法的构造函数 A(int ,int ),则通过此方法后就会把配置文件中的("1","1")转换为 (1,1)
// 缓存中的值可能是原始值也有可能是最终值
if (argsToResolve != null) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve);
}
}

// <3>
if (factoryMethodToUse == null || argsToUse == null) {
// 获取工厂方法的类全名称
factoryClass = ClassUtils.getUserClass(factoryClass);

List<Method> candidates = null;
if (mbd.isFactoryMethodUnique) {
if (factoryMethodToUse == null) {
factoryMethodToUse = mbd.getResolvedFactoryMethod();
}
if (factoryMethodToUse != null) {
candidates = Collections.singletonList(factoryMethodToUse);
}
}
if (candidates == null) {
candidates = new ArrayList<>();
// 获取所有待定方法
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
for (Method candidate : rawCandidates) {
// 检索所有方法,这里是对方法进行过滤
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
candidates.add(candidate);
}
}
}

// 创建 Bean
if (candidates.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
Method uniqueCandidate = candidates.get(0);
if (uniqueCandidate.getParameterCount() == 0) {
mbd.factoryMethodToIntrospect = uniqueCandidate;
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}

// 排序构造函数
// public 构造函数优先参数数量降序,非 public 构造函数参数数量降序
if (candidates.size() > 1) { // explicitly skip immutable singletonList
candidates.sort(AutowireUtils.EXECUTABLE_COMPARATOR);
}

// 用于承载解析后的构造函数参数的值
ConstructorArgumentValues resolvedValues = null;
boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Method> ambiguousFactoryMethods = null;

int minNrOfArgs;
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
// <2.3> getBean() 没有传递参数,则需要解析保存在 BeanDefinition 构造函数中指定的参数
if (mbd.hasConstructorArgumentValues()) {
// 构造函数的参数
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
// 解析构造函数的参数
// 将该 bean 的构造函数参数解析为 resolvedValues 对象,其中会涉及到其他 bean
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
else {
minNrOfArgs = 0;
}
}

Deque<UnsatisfiedDependencyException> causes = null;// 记录 UnsatisfiedDependencyException 异常的集合

// 遍历 candidates 数组
for (Method candidate : candidates) {
int parameterCount = candidate.getParameterCount();

if (parameterCount >= minNrOfArgs) {
// 保存参数的对象
ArgumentsHolder argsHolder;

// 方法体的参数
Class<?>[] paramTypes = candidate.getParameterTypes();
// #getBean(...) 传递了参数
if (explicitArgs != null) {
// 显示给定参数,参数长度必须完全匹配
if (paramTypes.length != explicitArgs.length) {
continue;
}
// 根据参数创建参数持有者 ArgumentsHolder 对象
argsHolder = new ArgumentsHolder(explicitArgs);
}
else {
// 为提供参数,解析构造参数
try {
String[] paramNames = null;
// 获取 ParameterNameDiscoverer 对象
// ParameterNameDiscoverer 是用于解析方法和构造函数的参数名称的接口,为参数名称探测器
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
// 获取指定构造函数的参数名称
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
// 在已经解析的构造函数参数值的情况下,创建一个参数持有者 ArgumentsHolder 对象
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
paramTypes, paramNames, candidate, autowiring, candidates.size() == 1);
}
catch (UnsatisfiedDependencyException ex) {
// 若发生 UnsatisfiedDependencyException 异常,添加到 causes 中。
if (logger.isTraceEnabled()) {
logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName + "': " + ex);
}
// Swallow and try next overloaded factory method.
if (causes == null) {
causes = new ArrayDeque<>(1);
}
causes.add(ex);
continue; // continue ,继续执行
}
}

// isLenientConstructorResolution 判断解析构造函数的时候是否以宽松模式还是严格模式
// 严格模式:解析构造函数时,必须所有的都需要匹配,否则抛出异常
// 宽松模式:使用具有"最接近的模式"进行匹配
// typeDiffWeight:类型差异权重
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this factory method if it represents the closest match.
// 代表最接近的类型匹配,则选择作为构造函数
if (typeDiffWeight < minTypeDiffWeight) {
factoryMethodToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousFactoryMethods = null;
}
// 如果具有相同参数数量的方法具有相同的类型差异权重,则收集此类型选项
// 但是,仅在非宽松构造函数解析模式下执行该检查,并显式忽略重写方法(具有相同的参数签名)
else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
!mbd.isLenientConstructorResolution() &&
paramTypes.length == factoryMethodToUse.getParameterCount() &&
!Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
// 查找到多个可匹配的方法
if (ambiguousFactoryMethods == null) {
ambiguousFactoryMethods = new LinkedHashSet<>();
ambiguousFactoryMethods.add(factoryMethodToUse);
}
ambiguousFactoryMethods.add(candidate);
}
}
}

// 没有可执行的工厂方法,抛出异常
if (factoryMethodToUse == null || argsToUse == null) {
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
List<String> argTypes = new ArrayList<>(minNrOfArgs);
if (explicitArgs != null) {
for (Object arg : explicitArgs) {
argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
}
}
else if (resolvedValues != null) {
Set<ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());
valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
valueHolders.addAll(resolvedValues.getGenericArgumentValues());
for (ValueHolder value : valueHolders) {
String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :
(value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));
argTypes.add(argType);
}
}
String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"No matching factory method found: " +
(mbd.getFactoryBeanName() != null ?
"factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +
"factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " +
"Check that a method with the specified name " +
(minNrOfArgs > 0 ? "and arguments " : "") +
"exists and that it is " +
(isStatic ? "static" : "non-static") + ".");
}
else if (void.class == factoryMethodToUse.getReturnType()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Invalid factory method '" + mbd.getFactoryMethodName() +
"': needs to have a non-void return type!");
}
else if (ambiguousFactoryMethods != null) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous factory method matches found in bean '" + beanName + "' " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousFactoryMethods);
}

if (explicitArgs == null && argsHolderToUse != null) {
// 将解析的构造函数加入缓存
mbd.factoryMethodToIntrospect = factoryMethodToUse;
argsHolderToUse.storeCache(mbd, factoryMethodToUse);
}
}

// 创建 Bean 对象,并设置到 bw 中
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
return bw;
}

private Object instantiate(String beanName, RootBeanDefinition mbd,
@Nullable Object factoryBean, Method factoryMethod, Object[] args) {

try {
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
this.beanFactory.getInstantiationStrategy().instantiate(mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args), this.beanFactory.getAccessControlContext());
}
else {
return this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean instantiation via factory method failed", ex);
}
}

以上该方法:确定工厂对象,然后获取构造函数和构造参数,最后调用 InstantiationStrategy 对象的 instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner, Constructor ctor, Object... args) 方法,来创建 Bean 实例

  • 一、<1>确定工厂对象

    首先获取工厂方法名:

    • 若工厂方法名不为空,则调用 AbstractAutowireCapableBeanFactory.getBean(String name) 方法,获取工厂对象,
    • 若为空,则可能为一个静态工厂,对于静态工厂则必须提供工厂类的全类名,同时设置 factoryBean = null
  • 二、<2>构造参数确认

    工厂对象确定后,则是确认构造参数。构造参数的确认主要分为三种情况:

    • explicitArgs 参数

    • 缓存中获取

    • 配置文件中解析

      <2.1>explicitArgs 参数

      explicitArgs 参数,是我们调用 getBean(...) 方法时传递进来的。一般该参数,该参数就是用于初始化 Bean 时所传递的参数。如果该参数不为空,则可以确定构造函数的参数就是它了。

      <2.2>缓存中获取

      在该方法的最后,我们会发现这样一段 argsHolderToUse.storeCache(mbd, factoryMethodToUse) 代码。这段代码主要是将构造函数、构造参数保存到缓存中:

      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
      // ConstructorResolver.ArgumentsHolder.java
      public void storeCache(RootBeanDefinition mbd, Executable constructorOrFactoryMethod) {
      synchronized (mbd.constructorArgumentLock) {
      mbd.resolvedConstructorOrFactoryMethod = constructorOrFactoryMethod;
      mbd.constructorArgumentsResolved = true;
      if (this.resolveNecessary) {
      mbd.preparedConstructorArguments = this.preparedArguments;
      } else {
      mbd.resolvedConstructorArguments = this.arguments;
      }
      }
      }

      // RootBeanDefinition.java
      // 构造函数的缓存锁
      final Object constructorArgumentLock = new Object();

      // 缓存已经解析的构造函数或者工厂方法
      @Nullable
      Executable resolvedConstructorOrFactoryMethod;

      // 标记字段,标记构造函数、参数已经解析了。默认为 `false`
      boolean constructorArgumentsResolved = false;

      // 缓存已经解析的构造函数参数,包可见字段。
      @Nullable
      Object[] resolvedConstructorArguments;

      从缓存中获取就是提取以上几个参数的值。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      // ConstructorResolver.java

      // 没有指定,则尝试从配置文件中解析
      Object[] argsToResolve = null;
      // <2.2> 首先尝试从缓存中获取
      synchronized (mbd.constructorArgumentLock) {
      // 获取缓存中的构造函数或者工厂方法
      factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
      if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
      // Found a cached factory method...
      // 获取缓存中的构造参数
      argsToUse = mbd.resolvedConstructorArguments;
      if (argsToUse == null) {
      // 获取缓存中的构造函数参数的包可见字段
      argsToResolve = mbd.preparedConstructorArguments;
      }
      }
      }
      // 缓存中存在,则解析存储在 BeanDefinition 中的参数
      // 如给定方法的构造函数 A(int ,int ),则通过此方法后就会把配置文件中的("1","1")转换为 (1,1)
      // 缓存中的值可能是原始值也有可能是最终值
      if (argsToResolve != null) {
      argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
      }
      • 如果缓存中存在构造参数,则需要调用resolvePreparedArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw, Executable executable, Object[] argsToResolve, boolean fallback)方法,进行转换。
      • 因为缓存中的值有可能是最终值,也有可能不是最终值。比如我们构造函数中的类型为 Integer 类型的 1 ,但是原始的参数类型有可能是 String 类型的 "1" ,所以即便是从缓存中得到了构造参数,也需要经过一番的类型转换确保参数类型完全对应

      <2.3>配置文件中解析

      即没有通过传递参数的方式传递构造参数,缓存中也没有,那就只能通过解析配置文件获取构造参数了。在 bean 解析类的博文中我们了解了,配置文件中的信息都会转换到 BeanDefinition 实例对象中,所以配置文件中的参数可以直接通过 BeanDefinition 对象获取。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      // AbstractAutowireCapableBeanFactory.java

      // <2.3> getBean() 没有传递参数,则需要解析保存在 BeanDefinition 构造函数中指定的参数
      if (mbd.hasConstructorArgumentValues()) {
      // <2.3.1> 构造函数的参数
      ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
      resolvedValues = new ConstructorArgumentValues();
      // <2.3.2> 解析构造函数的参数
      // 将该 bean 的构造函数参数解析为 resolvedValues 对象,其中会涉及到其他 bean
      minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
      }
      • <2.3.1> ,通过 BeanDefinition 的 getConstructorArgumentValues() 方法,就可以获取构造信息了。
      • <2.3.2> ,有了构造信息就可以获取相关的参数值信息了,获取的参数信息包括直接值和引用,这一步骤的处理交由 resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw, ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) 方法来完成。该方法会将构造参数信息解析为 resolvedValues 对象 并返回解析到的参数个数 minNrOfArgs
  • <3>构造函数

    确定构造参数后,下一步则是确定构造函数。

    • 第一步,是通过 getCandidateMethods() 方法,获取所有的构造方法,同时对构造方法进行刷选。
    • 然后,在对其进行排序处理(candidates.sort(AutowireUtils.EXECUTABLE_COMPARATOR))。排序的主要目的,是为了能够更加方便的找到匹配的构造函数,因为构造函数的确认是根据参数个数确认的。排序的规则是:先按照 public / 非 public 构造函数升序,再按照构造参数数量降序

    通过迭代 candidates(包含了所有要匹配的构造函数)的方式,依次比较其参数:

    • 如果显示提供了参数(explicitArgs != null),则直接比较两者长度是否相等,如果相等则表示找到了,否则继续比较。
    • 如果没有显示提供参数,则需要获取 org.springframework.core.ParameterNameDiscoverer 对象。该对象为参数名称探测器,主要用于发现方法和构造函数的参数名称。

    将参数包装成 ConstructorResolver.ArgumentsHolder 对象。该对象用于保存参数,我们称之为参数持有者。当将对象包装成 ArgumentsHolder 对象后,我们就可以通过它来进行构造函数匹配。匹配分为严格模式和宽松模式:

    • 严格模式:解析构造函数时,必须所有参数都需要匹配,否则抛出异常。
    • 宽松模式:使用具有”最接近的模式”进行匹配。

    判断的依据是根据 BeanDefinition 的 isLenientConstructorResolution 属性(该参数是我们在构造 AbstractBeanDefinition 对象是传递的)来获取类型差异权重(typeDiffWeight) 的。

    • 如果 typeDiffWeight < minTypeDiffWeight ,则代表“最接近的模式”,选择其作为构造函数。
    • 否则,只有两者具有相同的参数数量,且类型差异权重相等才会纳入考虑范围。
  • <4>创建Bean实例

    工厂对象、构造函数、构造参数都已经确认了,则最后一步就是调用 org.springframework.beans.factory.support.InstantiationStrategy 对象的 .instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner, Object factoryBean, final Method factoryMethod, @Nullable Object... args) 方法,来创建 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
    @Override
    public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,@Nullable Object factoryBean, final Method factoryMethod, Object... args) {
    try {
    // 设置 Method 可访问
    if (System.getSecurityManager() != null) {
    AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    ReflectionUtils.makeAccessible(factoryMethod);
    return null;
    });
    }
    else {
    ReflectionUtils.makeAccessible(factoryMethod);
    }

    // 获得原 Method 对象
    Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
    try {
    // 设置新的 Method 对象,到 currentlyInvokedFactoryMethod 中
    currentlyInvokedFactoryMethod.set(factoryMethod);
    // <x> 创建 Bean 对象
    Object result = factoryMethod.invoke(factoryBean, args);
    // 未创建,则创建 NullBean 对象
    if (result == null) {
    result = new NullBean();
    }
    return result;
    }
    finally {
    // 设置老的 Method 对象,到 currentlyInvokedFactoryMethod 中
    if (priorInvokedFactoryMethod != null) {
    currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
    }
    else {
    currentlyInvokedFactoryMethod.remove();
    }
    }
    }
    catch (IllegalArgumentException ex) {throw new BeanInstantiationException(factoryMethod,
    "Illegal arguments to factory method '" + factoryMethod.getName() + "'; " +
    "args: " + StringUtils.arrayToCommaDelimitedString(args), ex);
    }
    catch (IllegalAccessException ex) {
    throw new BeanInstantiationException(factoryMethod,
    "Cannot access factory method '" + factoryMethod.getName() + "'; is it public?", ex);
    }
    catch (InvocationTargetException ex) {
    String msg = "Factory method '" + factoryMethod.getName() + "' threw exception";
    if (bd.getFactoryBeanName() != null && owner instanceof ConfigurableBeanFactory &&
    ((ConfigurableBeanFactory) owner).isCurrentlyInCreation(bd.getFactoryBeanName())) {
    msg = "Circular reference involving containing bean '" + bd.getFactoryBeanName() + "' - consider " +
    "declaring the factory method as static for independence from its containing instance. " + msg;
    }
    throw new BeanInstantiationException(factoryMethod, msg, ex.getTargetException());
    }
    }

    核心的部分,在于 <x> 处,利用 Java 反射执行工厂方法并返回创建好的实例:

    1
    2
    3
    // SimpleInstantiationStrategy.java

    Object result = factoryMethod.invoke(factoryBean, args);

二十一、创建Bean之实例化Bean对象一
http://www.muzili.ren/2022/06/11/创建Bean之实例化Bean对象1/
作者
jievhaha
发布于
2022年6月11日
许可协议