❝你的赞是我最大的动力,期待与你共同进步
❞
1.开篇
上一篇文章学习了在Spring中如何通过工厂方法来实例化对象的,详细分析了createBeanInstance()
方法中调用的instantiateUsingFactoryMethod()
方法,今天这个片文章,将来分析另一个被调用的方法 determineConstructorsFromBeanPostProcessors()
。方法入口如下:
在这个的实现中,我们又看到了非常熟悉的
BeanPostProcessors
的处理,代码如下:
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;
}
从上述代码中,可以看到 Spring 中的处理方式就是先获取到所有的 BeanPostProcessors
的子类实现,然后循环判断,如果有符合条件的,
那么就调用该类的 determineCandidateConstructors()
方法,完成相应的处理。
在文章正式开始之前,又到了问问题的时候了,
ibp.determineCandidateConstructors()
在执行 determineCandidateConstructors()
方法的 BeanPostProcessor
的实现类中,有一个 AutowiredAnnotationBeanPostProcessor
,
我这里有一个问题,就是这个类是在什么时候放到 BeanDefinitionMap
中的呢?「请查看Spring容器初始化之先发五虎」。
2 你真的知道Spring如何选择构造器吗?
文章开始之前,还是要从使用场景入手,然后在通过源码来分析,毕竟源码是不会骗人的。。。
2.1情形一
@Service
public class DemoServiceOne {
}
2.2情形二
@Service
public class DemoServiceOne {
@Autowired
DemoServiceTwo demoServiceTwo;
public DemoServiceOne(){}
public DemoServiceOne(DemoServiceTwo demoServiceTwo){
this.demoServiceTwo = demoServiceTwo;
}
}
2.3情形三
@Service
public class DemoServiceOne {
@Autowired
DemoServiceTwo demoServiceTwo;
@Autowired
DemoServiceThree demoServiceThree;
public DemoServiceOne(DemoServiceTwo demoServiceTwo){
this.demoServiceTwo = demoServiceTwo;
}
public DemoServiceOne(DemoServiceThree demoServiceThree, DemoServiceTwo demoServiceTwo){
this.demoServiceTwo = demoServiceTwo;
this.demoServiceThree = demoServiceThree;
}
}
2.4情形四
@Service
public class DemoServiceOne {
@Autowired
DemoServiceTwo demoServiceTwo;
@Autowired
DemoServiceThree demoServiceThree;
public DemoServiceOne(DemoServiceTwo demoServiceTwo){
this.demoServiceTwo = demoServiceTwo;
}
@Autowired
public DemoServiceOne(DemoServiceThree demoServiceThree, DemoServiceTwo demoServiceTwo){
this.demoServiceTwo = demoServiceTwo;
this.demoServiceThree = demoServiceThree;
}
}
3 AutowiredAnnotationBeanPostProcessor 类中的方法
从代码的实现可以看出,对于一个放在注册到容器中的 BeanName
,都会做一次这个判断。至于没有交给Spring的类,这里当然是不会做处理了。
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
throws BeanCreationException {
// Let's check for lookup methods here...
// 首先检查 lookup 方法
if (!this.lookupMethodsChecked.contains(beanName)) {
try {
ReflectionUtils.doWithMethods(beanClass, method -> {
Lookup lookup = method.getAnnotation(Lookup.class);
if (lookup != null) {
Assert.state(this.beanFactory != null, "No BeanFactory available");
LookupOverride override = new LookupOverride(method, lookup.value());
try {
RootBeanDefinition mbd = (RootBeanDefinition)
this.beanFactory.getMergedBeanDefinition(beanName);
mbd.getMethodOverrides().addOverride(override);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(beanName,
"Cannot apply @Lookup to beans without corresponding bean definition");
}
}
});
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
}
this.lookupMethodsChecked.add(beanName);
}
// Quick check on the concurrent map first, with minimal locking.
// 从缓存中查找
Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
// 缓存中没有
if (candidateConstructors == null) {
// 同步代码块
synchronized (this.candidateConstructorsCache) {
candidateConstructors = this.candidateConstructorsCache.get(beanClass);
if (candidateConstructors == null) {
Constructor<?>[] rawCandidates;
try {
// 获取 Bean的声明的所有构造器, 无惨构造器也会被拿到
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 大小为 前面获取到的类的构造参数个数
List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
//存放依赖注入的required=true的构造器
Constructor<?> requiredConstructor = null;
//存放默认构造器
Constructor<?> defaultConstructor = null;
//获取主要的构造器,大多数的情况下为 null
Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
int nonSyntheticConstructors = 0;
for (Constructor<?> candidate : rawCandidates) {
// 判断构造器是否为合成构造器,只要是我们自己申明的都不是合成构造器
if (!candidate.isSynthetic()) {
// 不是合成构造器,标记非合成构造器的数字 加一
nonSyntheticConstructors++;
}
else if (primaryConstructor != null) {
continue;
}
//查找当前构造器上的注解,有些构造器上面可能有注解,有些没有。这里要做区分
AnnotationAttributes ann = findAutowiredAnnotation(candidate);
if (ann == null) {
// 没有注解
// 获取创建 Bean使用的 class
Class<?> userClass = ClassUtils.getUserClass(beanClass);
if (userClass != beanClass) {
try {
Constructor<?> superCtor =
userClass.getDeclaredConstructor(candidate.getParameterTypes());
ann = findAutowiredAnnotation(superCtor);
}
catch (NoSuchMethodException ex) {
// Simply proceed, no equivalent superclass constructor found...
}
}
}
if (ann != null) {
// 有注解
if (requiredConstructor != null) {
//已经存在一个required=true的构造器了,抛出异常
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructor: " + candidate +
". Found constructor with 'required' Autowired annotation already: " +
requiredConstructor);
}
//判断此注解上的required属性 默认为 true 可设置为 false
// 这里是用来处理两个注解一个 required 为 true,一个 为false的情况
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);
}
//若为true
//将当前构造器赋值给 requiredConstructor
requiredConstructor = candidate;
}
// 当前的构造器添加到候选的构造器集合中
candidates.add(candidate);
}
//如果该构造函数上没有注解,再判断构造函数上的参数个数是否为0
else if (candidate.getParameterCount() == 0) {
//如果没有参数,加入defaultConstructor集合,这里可以看出没有构造器的情况下,将无参构造器赋值给默认的构造器
defaultConstructor = candidate;
}
}
//适用的构造器集合若不为空
if (!candidates.isEmpty()) {
// Add default constructor to list of optional constructors, as fallback.
//若没有required=true的构造器
if (requiredConstructor == null) {
if (defaultConstructor != null) {
//将defaultConstructor集合的构造器加入适用构造器集合
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));
}
}
//将适用构造器集合赋值给将要返回的构造器集合
candidateConstructors = candidates.toArray(new Constructor<?>[0]);
}
//如果适用的构造器集合为空,且Bean只有一个构造器并且此构造器参数数量大于0
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
//就使用此构造器来初始化
candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
}
//如果构造器有两个,且默认构造器不为空
else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
//使用默认构造器返回
candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
}
else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
candidateConstructors = new Constructor<?>[] {primaryConstructor};
}
else {
// 都不符合 初始化 candidateConstructors 若不初始化 后面的判断会有问题
candidateConstructors = new Constructor<?>[0];
}
//放入缓存,方便下一次调用,不需要上述的解析过程了,直接在缓存中获取
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
}
}
// 这里可以看到对 candidateConstructors 的初始化是有意义的
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
首先来分析一下上述代码主要住了什么事,选取主要的步骤进行说明:
①:首先获取类的构造方法,记录在 Constructor<?>[] rawCandidates
中
❝rawCandidates = beanClass.getDeclaredConstructors();无参构造器也会被拿到。下图中,以类中没有构造器的情形举例
❞
②:
for
循环 rawCandidates
对其中的每一个构造器进行判断
③:判断构造器上是否加了注解
- 3.1 有加注解
❝
先判断requiredConstructor集合是否为空, 若不为空则代表之前已经有一个required=true的构造器了,两个true将抛出异常. 再判断candidates 集合是否为空,若不为空则表示之前已经有一个打了注解的构造器,若有required又是true,抛出异常. 若上述判断都通过了,将当前构造器赋值给 requiredConstructor集合中,再放入candidates集合中。
❞ - 3.2 没有加注解
❝
如果是无惨构造器则赋值给 defaultConstructor,其他的构造器不做处理,在会后返回的时候返回null
❞
④:没有加注解且参数的个数为 0。将当前 for
循环的构造方法赋值给 defaultConstructor
defaultConstructor = candidate;
⑤:确定构造器
这里确定构造器还是要结合前面的代码去看。
4 情形分析
构造器上没有注解的情况:
无参构造器将直接加入defaultConstructor集合中,无论是否申明。但是本方法最后返回的是
null
。最终的实例化是通过默认的构造函数来完成的instantiateBean(beanName, mbd)
。在构造器数量只有一个且有参数时,此唯一有参构造器将加入candidateConstructors集合中。最后返回。
在构造器数量大于1个,无论是否申明无参构造器的情况下,将返回一个空的candidateConstructors集合,也就是没有找到构造器。
❝
不过这里需要区分一下是否声明无惨构造器: 如果未声明 defaultConstructor 为null 如果声明了 defaultConstructor 不为null
❞多个构造器同时存且不包含注解
综上所述,在构造器没有注解的情况下,如果有且仅有一个非无惨的构造器,那么本方法返回的就是这个构造器。如果大于一个或则只有一个
无参构造器,那么该方法返回的都是 null
。
- 构造器上有注解的情况:
构造器上有注解的情况需要判断required属性:
两个构造器上都有
@Autowired
且 required属性都为true 抛出异常❝
throw new BeanCreationException(beanName, "Invalid autowire-marked constructor: " + candidate + ". Found constructor with 'required' Autowired annotation already: " + requiredConstructor);
❞两个构造器上都有
@Autowired
一个 required属性都为true 另一个 required属性都为false 抛出异常❝
throw new BeanCreationException(beanName, "Invalid autowire-marked constructors: " + candidates + ". Found constructor with 'required' Autowired annotation: " + candidate);
❞两个构造器上都有
@Autowired
且 required属性都为false 则正常通过,后面的方法会确定使用哪一个
5 总结
- 对象中存在多个未被注解的构造器
determineCandidateConstructors()
方法都会返回null
。「这里有彩蛋,后面文章会提到」
- 对象中存在多个未被注解的构造器
对象中有且仅有一个未被注入的构造器
- 若该构造器为无参的,那么
determineCandidateConstructors()
返回null
- 若该构造构器为有参的,那么
determineCandidateConstructors()
返回 该构造器
- 若该构造器为无参的,那么
- 仅有一个注入的构造器,则使用该构造器
- 有两个注入的构造器
- required 都为
true
抛出异常 - required 一个为
true
另一个为false
抛出异常 - required 都为
false
正常通过
- required 都为
- 有两个注入的构造器
这篇文章中对Spring中通过使用 BeanPostProcessor
的实现类来完成构造器的确认进行了分析。当我们实例化一个对象的时候,构造方法确定了,
那么就可以通过使用构造方法来实例化了。但是,通过上面的分析发现,可能会有多个构造方法存在的情况,那么在这种情况下,Spring是如何确定使用哪个构造方法的,
也就是大名鼎鼎的推断构造器,下一篇文章中,将进行分析。
本文使用 mdnice 排版