推断构造方法源码解析
Spring 在推断构造方法的逻辑上面写的实在太复杂了,构造种类贼多贼多,恕我实力有限,这里的话算不上源码分析,只能说是原理吧,这我只考虑了平常开发会遇到的,什么getBean去添加参数的、BeanDefinition去填充的我都一概跳过,看不懂一点(比如多参构造参数相同的情况下(@Autowired注解修饰后的required为false)会进行评分操作,有点复杂,感觉遇不着就不想研究了)。
(这篇博客可能有点水了)
一、确认候选构造——AutowireAnnotationBeanPostProcessor#determineCandidateConstructors
确认候选的构造也是通过 BeanPostProcessor 来进行的(SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors
),引进的代码如下:
// Candidate constructors for autowiring?
// 提供一个扩展点,可以利用SmartInstantiationAwareBeanPostProcessor来控制用beanClass中的哪些构造方法
// 比如AutowiredAnnotationBeanPostProcessor会把加了@Autowired注解的构造方法找出来,具体看代码实现会更复杂一点
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
@Nullable
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
throws BeansException {
if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
Constructor<?>[] ctors = bp.determineCandidateConstructors(beanClass, beanName);
if (ctors != null) {
return ctors;
}
}
}
return null;
}
Spring 实现的 SmartInstantiationAwareBeanPostProcessor 的 determineCandidateConstructors 方法中就一个对其进行实现了——AutowireAnnotationBeanPostProcessor。
下面俺对其核心代码进行解析:
@Override
@Nullable
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
throws BeanCreationException {
// Quick check on the concurrent map first, with minimal locking.
Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
if (candidateConstructors == null) {
// Fully synchronized resolution now...
synchronized (this.candidateConstructorsCache) {
candidateConstructors = this.candidateConstructorsCache.get(beanClass);
if (candidateConstructors == null) {
Constructor<?>[] rawCandidates;
try {
// 拿到所有的构造方法
rawCandidates = beanClass.getDeclaredConstructors();
} catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
}
List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
// 用来记录required为true的构造方法,一个类中只能有一个required为true的构造方法
Constructor<?> requiredConstructor = null;
// 用来记录默认无参的构造方法
Constructor<?> defaultConstructor = null;
// 遍历每个构造方法
for (Constructor<?> candidate : rawCandidates) {
// 当前遍历的构造方法是否写了@Autowired
MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
// 当前构造方法上加了@Autowired
if (ann != null) {
// 整个类中如果有一个required为true的构造方法,那就不能有其他的加了@Autowired的构造方法
// 若存在required为true的还存在其他的@Autowired注解就抛出异常
if (requiredConstructor != null) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructor: " + candidate +
". Found constructor with 'required' Autowired annotation already: " +
requiredConstructor);
}
boolean required = determineRequiredStatus(ann);
if (required) {
if (!candidates.isEmpty()) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructors: " + candidates +
". Found constructor with 'required' Autowired annotation: " +
candidate);
}
// 记录唯一一个required为true的构造方法
requiredConstructor = candidate;
}
// 记录所有加了@Autowired的构造方法,不管required是true还是false
// 如果默认无参的构造方法上也加了@Autowired,那么也会加到candidates中
candidates.add(candidate);
// 从上面代码可以得到一个结论,在一个类中,要么只能有一个required为true的构造方法,要么只能有一个或多个required为false的方法
} else if (candidate.getParameterCount() == 0) {
// 记录唯一一个无参的构造方法
defaultConstructor = candidate;
}
// 有可能存在有参、并且没有添加@Autowired的构造方法
}
if (!candidates.isEmpty()) {
// Add default constructor to list of optional constructors, as fallback.
// 如果不存在一个required为true的构造方法,则所有required为false的构造方法和无参构造方法都是合格的
if (requiredConstructor == null) {
if (defaultConstructor != null) {
candidates.add(defaultConstructor);
} else if (candidates.size() == 1 && logger.isInfoEnabled()) {
logger.info("Inconsistent constructor declaration on bean with name '" + beanName +
"': single autowire-marked constructor flagged as optional - " +
"this constructor is effectively required since there is no " +
"default constructor to fall back to: " + candidates.get(0));
}
}
// 如果只存在一个required为true的构造方法,那就只有这一个是合格的
candidateConstructors = candidates.toArray(new Constructor<?>[0]);
}
// 没有添加了@Autowired注解的构造方法,并且类中只有一个构造方法,并且是有参的
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
candidateConstructors = new Constructor<?>[]{rawCandidates[0]};
}
else {
// 如果有多个有参、并且没有添加@Autowired的构造方法,是会返回空的
candidateConstructors = new Constructor<?>[0];
}
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
}
}
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
就是说只有三种情况有可用的构造(这里是指会有返回的候选构造方法):
- 使用了 @Autowired 注解,有且只有一个 required 为 true;
- 使用了 @Autowired 注解,required 都为 false;
- 没有使用 @Autowired 注解,有且只有一个多参构造。
通过这些代码的解析可以知道:
- 含有多个参数多个构造和只有一个无参的都会走
instantiateBean
的逻辑,去通过无参构造去实例化,如果没有的话就抛异常咯,换句话说就是没用@Autowired注解就是去找无参,没有就抛异常。 - 有且只有一个 @Autowired 注解且required为true,有多个 @Autowired 注解,但是 required 都为 false,那么就是通过
autowireConstructor
方法去实现 Spring 的自动构造。
二、autowireConstructor 方法源码解析
太难了,看不了一点,直接阐述源码流程(和上面的接着的)。
上面确认候选构造的时候还有三种情况我们需要考虑:
- 使用了 @Autowired 注解,有且只有一个 required 为 true;
- 使用了 @Autowired 注解,required 都为 false;
- 没有使用 @Autowired 注解,有且只有一个多参构造。
也就是上面这三种情况会进入到 autowireConstructor
方法。
下面阐述一下流程:
- 首先是对构造进行个排序,以参数的个数降序排序,就是参数个数多的在前面:
- 然后去调用
beanFactory#resolveDependency
方法去给参数进行填充参数; - 如果根据当前构造方法找到了对应的构造方法参数值,那么这个构造方法就是可用的,但是不一定这个构造方法就是最佳的,所以这里会涉及到是否有多个构造方法匹配了同样的值,这个时候就会用值和构造方法类型进行匹配程度的打分,找到一个最匹配的
也就是说构造方法要满足可用的话,必须所有的参数都是Spring容器中拥有的,可以注入的。
三、总结
本篇并不是Spring所有推断构造方法的逻辑,只是其中的一部分——AutowireAnnotationBeanPostProcessor#determineCandidateConstructors
中推断出来的构造方法是怎么处理的。
主要就是有无 @Autowired 注解俩各方面。
当有多个构造 @Autowired 注解,但是 required 都为 false 的话,考虑 autowireConstructor 的逻辑。先是将所候选的构造参数个数降序排序,然后逐个去匹配,看看参数是否都能在容器中找到,找不到就换下一个,找到就用该构造。