Spring构造器注入源码分析笔记

前言

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
/**
* Create a new instance for the specified bean, using an appropriate instantiation strategy:
* factory method, constructor autowiring, or simple instantiation.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @param args explicit arguments to use for constructor or factory method invocation
* @return a BeanWrapper for the new instance
* @see #obtainFromSupplier
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
* @see #instantiateBean
*/
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
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());
}

Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}

if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}

// Shortcut when re-creating the same bean...
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
}

// Candidate constructors for autowiring?
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}

// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}

// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
}

在上边的代码中,这一段逻辑是关键:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
   ...

// 从 Bean 的 class 中尝试获取合适的构造器(构造器元数据,反射中的概念)
// Candidate constructors for autowiring?
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 如果有,则用找到的构造器进行 Bean 的实例化(以及依赖注入)
return autowireConstructor(beanName, mbd, ctors, args);
}

// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}

// 如果没有,则用默认构造器进行实例化
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);

这段逻辑翻译成自然语言就是:从 Bean 的 class 中尝试获取合适的构造器(构造器元数据,反射中的概念),如果有,则用找到的构造器进行 Bean 的实例化(以及依赖注入),如果没有,则用默认构造器进行实例化。

来看“从 Bean 的 class 中尝试获取合适的构造器”这一块:

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
/**
* Determine candidate constructors to use for the given bean, checking all registered
* {@link SmartInstantiationAwareBeanPostProcessor SmartInstantiationAwareBeanPostProcessors}.
* @param beanClass the raw class of the bean
* @param beanName the name of the bean
* @return the candidate constructors, or {@code null} if none specified
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors
*/
@Nullable
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
throws BeansException {

if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
if (ctors != null) {
return ctors;
}
}
}
}
return null;
}

这里会迭代当前所有的 BeanPostProcessors ,每次迭代的项目为 bp 当迭代到 AutowiredAnnotationBeanPostProcessor 类型的 bp 时,是可以执行其 determineCandidateConstructors 方法,然后通过这个方法拿到合适的构造器的 List,如果这个 List 不为空,则返回这个 List。

然后我们又回到 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance 这个方法,此时下面的 if 条件已经满足:

1
2
3
4
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}

就可以执行 autowireConstructor(beanName, mbd, ctors, args); 这个逻辑了,我们再来看这个逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* "autowire constructor" (with constructor arguments by type) behavior.
* Also applied if explicit constructor argument values are specified,
* matching all remaining arguments with beans from the bean factory.
* <p>This corresponds to constructor injection: In this mode, a Spring
* bean factory is able to host components that expect constructor-based
* dependency resolution.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @param ctors the chosen candidate constructors
* @param explicitArgs argument values passed in programmatically via the getBean method,
* or {@code null} if none (-> use constructor argument values from bean definition)
* @return a BeanWrapper for the new instance
*/
protected BeanWrapper autowireConstructor(
String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {

return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}

我们再进入 autowireConstructor(beanName, mbd, ctors, explicitArgs);

这个逻辑相当长,我们来捡出其中重要的一段来看:

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
...

// 迭代所有传入的构造器
for (Constructor<?> candidate : candidates) {
Class<?>[] paramTypes = candidate.getParameterTypes();

if (constructorToUse != null && argsToUse != null && argsToUse.length > paramTypes.length) {
// Already found greedy constructor that can be satisfied ->
// do not look any further, there are only less greedy constructors left.
break;
}
if (paramTypes.length < minNrOfArgs) {
continue;
}

ArgumentsHolder argsHolder;
if (resolvedValues != null) {
try {

// 这里是关键,这里的作用是找到构造器中所有参数的名字
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
}
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
}
catch (UnsatisfiedDependencyException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
}
// Swallow and try next constructor.
if (causes == null) {
causes = new LinkedList<>();
}
causes.add(ex);
continue;
}
}
else {
// Explicit arguments given -> arguments length must match exactly.
if (paramTypes.length != explicitArgs.length) {
continue;
}
argsHolder = new ArgumentsHolder(explicitArgs);
}

int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this constructor if it represents the closest match.
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
}
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}

...

注意这一段关键的逻辑,作用是找到构造器中所有参数的名字:

1
2
3
4
5
6
7
8
9
10
11
12

...

String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
}

...

先看 ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length); :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* Delegate for checking Java 6's {@link ConstructorProperties} annotation.
*/
private static class ConstructorPropertiesChecker {

@Nullable
public static String[] evaluate(Constructor<?> candidate, int paramCount) {
ConstructorProperties cp = candidate.getAnnotation(ConstructorProperties.class);
if (cp != null) {
String[] names = cp.value();
if (names.length != paramCount) {
throw new IllegalStateException("Constructor annotated with @ConstructorProperties but not " +
"corresponding to actual number of parameters (" + paramCount + "): " + candidate);
}
return names;
}
else {
return null;
}
}
}

这个逻辑实际上是获得构造器上标注的 java.beans.ConstructorProperties 注解,这个注解是 Java Bean 规范中的标准注解,在其中可以指定构造器参数的名字,Spring 可以通过它来获取用户通过注解这种方法指定的构造器参数名。

如果通过注解没获得到任何参数名的话,则会从 DefaultParameterNameDiscoverer 中尝试获取参数名,在 DefaultParameterNameDiscoverer 中包含了两个 ParameterNameDiscoverer 一个是用反射来获取参数名的 StandardReflectionParameterNameDiscoverer 另一个是用 asm 从本地变量表读取参数名的 LocalVariableTableParameterNameDiscoverer

1
2
3
4
5
6
7
8
9
10
11
12
public class DefaultParameterNameDiscoverer extends PrioritizedParameterNameDiscoverer {

public DefaultParameterNameDiscoverer() {
if (!GraalDetector.inImageCode()) {
if (KotlinDetector.isKotlinReflectPresent()) {
addDiscoverer(new KotlinReflectionParameterNameDiscoverer());
}
addDiscoverer(new StandardReflectionParameterNameDiscoverer());
addDiscoverer(new LocalVariableTableParameterNameDiscoverer());
}
}
}

这个 DefaultParameterNameDiscoverer 的父类 PrioritizedParameterNameDiscoverer 中包含了真正的获取逻辑:

1
2
3
4
5
6
7
8
9
10
11
@Override
@Nullable
public String[] getParameterNames(Constructor<?> ctor) {
for (ParameterNameDiscoverer pnd : this.parameterNameDiscoverers) {
String[] result = pnd.getParameterNames(ctor);
if (result != null) {
return result;
}
}
return null;
}

这个逻辑中实际上就是依次尝试用内部的 ParameterNameDiscoverer 来获取参数名,获取不到就尝试下一个,在这个例子里我们的类信息中不包含调试信息(也就是不包含参数名信息),因此 StandardReflectionParameterNameDiscoverer 拿不到,但是 LocalVariableTableParameterNameDiscoverer 是可以拿到的。

拿到了参数名后,执行 createArgumentArray:

1
2
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);

在这个方法中会执行这个逻辑将构造器封装成 MethodParameter

1
MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);

然后通过

1
2
Object autowiredArgument = resolveAutowiredArgument(
methodParam, beanName, autowiredBeanNames, converter, fallback);

按照构造器中参数类型和名字找到相应的 Bean 然后放入 ArgumentsHolder 中返回。

然后我们回到 org.springframework.beans.factory.support.ConstructorResolver#autowireConstructor 流程中,下一个重要流程是 bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));,这里就是实际上进行 Bean 的实例化了(这里面 constructorToUse 是前面流程中获得的构造器,而 argsToUse 是前面获得的 ArgumentsHolder)。