1.写在前面
上篇博客笔者主要讲了spring调用doCreateBean(beanName, mbdToUse, args);
方法的前面的一小部分,后面还有许多的东西没有讲,今天笔者打算继续往后讲。废话不多说,直接开启今天的博客之旅吧。这篇博客篇幅过长,请读者耐心享用。
2.Spring中推断构造函数
上篇博客中讲到doCreateBean(beanName, mbdToUse, args);
方法中的创建Bean的实例的方法createBeanInstance(beanName, mbd, args);
具体的代码如下:
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
// 获取Bean的Class,这儿获取的A.Class,因为笔者条件断点的是a
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());
}
//获取供给型的接口,直接创建Bean
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) {
// 这个参数只有在@Bean注解的方法的时候创建RootBeanDefinition的才会这个参数赋值,而@Bean注解的方法在上面
// instantiateUsingFactoryMethod(beanName, mbd, args);已经创建完成返回了。
// 所以这个判断只有在创建RootBeanDefinition的时候,同时它的工厂方法名为空,然后这个解析的工厂方法名不为空的时候,才会进入这个判断
// 已经缓存的构造函数
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
// constructorArgumentsResolved默认为false
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
//只有上面判断执行,这个判断才会执行,一般情况下不会执行
if (resolved) {
if (autowireNecessary) {
//通过自动装配的构造函数方式实例化Bean
return autowireConstructor(beanName, mbd, null, null);
}
else {
//实例化Bean
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);
}
上面的代码中间两个if的判断一般不会执行resolvedConstructorOrFactoryMethod
目前只有在解析@Bean
注解的时候,这个值才有值,而@Bean注解的方法,又会在instantiateUsingFactoryMethod(beanName, mbd, args);
方法的时候,创建好了对应Bean,然后直接返回了。所以这个条件要满足的话,应该是自己创建对应RootBeanDefinition
,然后对应的工厂方法名是为空,然后缓存的构造方法不为空,才会进中间的那几个if的判断。如果有其他用到的地方,目前笔者还是不知道的。如果有读者知道,可以告诉笔者,可能笔者后面继续看源码的时候,就可能会发现有的地方用到了这几个if的判断。目前没有发现。
开始今天的重点的方法determineConstructorsFromBeanPostProcessors(beanClass, beanName);
,这个方法就是推断构造方法的,就是前面的两种方式创建Bean的条件都不满足的情况下。废话不多说,直接看代码,具体的代码如下:
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
throws BeansException {
//这个判断是成立,不清楚的可以看下笔者的博客Spring源码系列(十一)Spring创建Bean的过程(一)
if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
//这儿取出来的是7个BeanPostProcessor(加了Aop的情况下)
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//实现这个SmartInstantiationAwareBeanPostProcessor的接口有三个ImportAwareBeanPostProcessor
// AutowiredAnnotationBeanPostProcessor AnnotationAwareAspectJautoProxyCreator
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
if (ctors != null) {
return ctors;
}
}
}
}
return null;
}
上面的判断是成立,看过笔者的Spring源码系列(十一)Spring创建Bean的过程(一)这篇博客,就知道这里判断为什么成立。以及有那7个BeanPostProcessor
,同时其中有那几个实现SmartInstantiationAwareBeanPostProcessor
接口的类,其中有三个,主要是ImportAwareBeanPostProcessor
、AutowiredAnnotationBeanPostProcessor
、AnnotationAwareAspectJautoProxyCreator
然后会分别执行其中determineCandidateConstructors(beanClass, beanName);
的方法。但是一个类中构造函数有很多种情况,于是笔者在下面的博客进行分类说明。
2.1默认的无参构造函数(没有加@Autowired)
第一种情况就是没有提供构造函数,就是一个默认的无参的函数,具体如下:
package com.ys.beanLife.bean;
import org.springframework.stereotype.Component;
@Component
public class A{
public A(){}
}
假设Spring要创建A类的Bean,这个时候分别会去执行上面三个类的中的determineCandidateConstructors(beanClass, beanName);
的方法。
第一次执行determineCandidateConstructors(beanClass, beanName);
方法:ImportAwareBeanPostProcessor
类,具体的代码如下:
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
可以发现这个类的这个方法的返回值就是null。所以可以直接跳过。
第二次执行determineCandidateConstructors(beanClass, beanName);
方法:AnnotationAwareAspectJautoProxyCreator
类,具体的代码如下:
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) {
return null;
}
可以发现这个类的这个方法的返回值就是null。所以可以直接跳过。
第三次执行determineCandidateConstructors(beanClass, beanName);
方法:AutowiredAnnotationBeanPostProcessor
类,具体的代码如下:
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
throws BeanCreationException {
// Let's check for lookup methods here...
// 处理LookUp注解,不是本篇博客的重点
if (!this.lookupMethodsChecked.contains(beanName)) {
if (AnnotationUtils.isCandidateClass(beanClass, Lookup.class)) {
try {
Class<?> targetClass = beanClass;
do {
ReflectionUtils.doWithLocalMethods(targetClass, 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");
}
}
});
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
}
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.
// 这才是本篇博客的重点,去推断构造方法
// 这儿取出来是空的,因为没有往其中put过
// 候选的构造函数
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 {
//从A类中取出所有的构造函数,这个时候取出来应该是一个无参的构造函数
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);
Constructor<?> requiredConstructor = null;
//默认的构造函数
Constructor<?> defaultConstructor = null;
//这个方法只对Kotlin有用,正常的情况直接返回null
Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
//不是合成的构造函数的个数
int nonSyntheticConstructors = 0;
//遍历所有的构造函数
for (Constructor<?> candidate : rawCandidates) {
//如果这个构造函数不是合成的,就给nonSyntheticConstructors变量加1,至于什么是合成的函数,笔者前面的博客有讲过
if (!candidate.isSynthetic()) {
nonSyntheticConstructors++;
}
//这个值默认为空,只有在是kotlin的情况可能不为空
else if (primaryConstructor != null) {
continue;
}
//查找这个构造方法中有没有加@Autowired注解,这儿也是为null
MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
if (ann == null) {
//获取这个类的要使用的类,如果这个类是Cglib的代理的话,就返回的父类,如果没有直接返回对应的类,这儿获取的A.class
Class<?> userClass = ClassUtils.getUserClass(beanClass);
//只有是代理的情况下会执行
if (userClass != beanClass) {
try {
//根据当前遍历的构造函数,获取父类的对应的构造函数
Constructor<?> superCtor =
userClass.getDeclaredConstructor(candidate.getParameterTypes());
//然后查找这个构造函数上是不是加了@Autowired注解
ann = findAutowiredAnnotation(superCtor);
}
catch (NoSuchMethodException ex) {
// Simply proceed, no equivalent superclass constructor found...
}
}
}
//这儿获取的值也是空,不会进入这个判断
if (ann != null) {
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);
}
requiredConstructor = candidate;
}
candidates.add(candidate);
}
//判断这个构造函数的参数的个数是不是等于0,这儿这个判断是成立的,给defaultConstructor赋了一个值
else if (candidate.getParameterCount() == 0) {
defaultConstructor = candidate;
}
}
//判断这个值是不是等于空,这儿这个集合等于空,这儿只有添加了@Autowired这个注解的时候,这个candidates才不为空
if (!candidates.isEmpty()) {
// Add default constructor to list of optional constructors, as fallback.
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));
}
}
candidateConstructors = candidates.toArray(new Constructor<?>[0]);
}
//找到所有的构造函数的长度等于1,同时这个构造函数的参数的长度大于0,这儿不满足
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
}
//非合成的构造函数的个数等于2,同时primaryConstructor这个值不等于null,这个值只有在kotlin的情况,可能不为空
//默认的构造函数的值不等于空,同时主要的构造函数不包含这个默认的构造函数,这个判断是不会成立的,直接跳过
else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
}
//非合成的构造函数的个数等于1,同时primaryConstructor这个值不等于null,这个值只有在kotlin的情况,可能不为空
//这个时候这个判断也不会成立
else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
candidateConstructors = new Constructor<?>[] {primaryConstructor};
}
//最后进入这个判断
else {
//候选构造函数的值等于空的数组,
candidateConstructors = new Constructor<?>[0];
}
//将这个候选构造函数的数组放入到候选构造函数的缓存中
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
}
}
//这个长度就是等于0,直接返回null
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
上面的代码走来获取的所有的构造函数然后存入到rawCandidates
变量中去,然后查找调用BeanUtils.findPrimaryConstructor(beanClass);
方法查找主要的构造函数,这个方法只对kotlin的有用,所以默认情况下这个方法的返回值都是为空,所以primaryConstructor
一般的情况下都是为空,然后开始遍历这些的构造函数,查找这些构造函数中不是合成的构造函数的个数,将这个个数存入到nonSyntheticConstructors
变量中去,然后这些方法的上有没有添加@Autowired
注解,如果这个类是cglib的代理的类,就查找它的父类的这个对应的构造方法上有没有添加@Autowired
注解,由于我们这儿是没有提供构造方法,默认的无参的。所以这些判断都是不会成立的。于是为判断这个构造函数的参数个数是不是等于0,如果是等于0,将这个构造函数存入到defaultConstructor
变量中去。最后进行对应的五个判断,前四个判断都是不成立的,于是直接进入最后一个判断,创建一个空的构造器函数的数组对象,最后将这个数据存到candidateConstructorsCache
变量中去,键是class,值是这个构造器函数的数组对象,最后判断这个数组的长度是不是大于0,如果大于0,返回这个数组,如果不大于0,直接返回null,所以这儿的结果是返回null。
总结:默认的构造无参构造函数(没有加@Autowired)的类,通过这个方法执行完后,返回的值是null
2.2有且只有一个构造函数(加了@Autowired)
第二种就是有且只有一个构造函数,我们这儿就提供一个默认无参的构造方法,并且这个方法加了@Autowired
注解,具体的代码如下:
package com.ys.beanLife.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class A{
@Autowired()
public A() {
}
}
由于前面的两个的类的determineCandidateConstructors(beanClass, beanName);
的方法都是返回null,所以我们直接看AutowiredAnnotationBeanPostProcessor
类的determineCandidateConstructors(beanClass, beanName);
的方法,具体的代码如下:
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
throws BeanCreationException {
//省略处理LookUp注解的方法
// Quick check on the concurrent map first, with minimal locking.
// 这才是本篇博客的重点,去推断构造方法
// 这儿取出来是空的,因为没有往其中put过
// 候选的构造函数
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 {
//从A类中取出所有的构造函数
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);
//用来存加了@Autowired(required=true)注解的构造方法
Constructor<?> requiredConstructor = null;
//默认的构造函数
Constructor<?> defaultConstructor = null;
//这个方法只对Kotlin有用,正常的情况直接返回null
Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
//不是合成的构造函数的个数
int nonSyntheticConstructors = 0;
//遍历所有的构造函数
for (Constructor<?> candidate : rawCandidates) {
//如果这个构造函数不是合成的,就给nonSyntheticConstructors变量加1,至于什么是合成的函数,笔者前面的博客有讲过
if (!candidate.isSynthetic()) {
nonSyntheticConstructors++;
}
//这个值默认为空,只有在是kotlin的情况可能不为空
else if (primaryConstructor != null) {
continue;
}
//查找这个构造方法中有没有加@Autowired注解,这儿不是null
MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
//在这种情况下,返回的值就不是空
if (ann == null) {
//获取这个类的要使用的类,如果这个类是Cglib的代理的话,就返回的父类,如果没有直接返回对应的类,这儿获取的A.class
Class<?> userClass = ClassUtils.getUserClass(beanClass);
//只有是代理的情况下会执行
if (userClass != beanClass) {
try {
//根据当前遍历的构造函数,获取父类的对应的构造函数
Constructor<?> superCtor =
userClass.getDeclaredConstructor(candidate.getParameterTypes());
//然后查找这个构造函数上是不是加了@Autowired注解
ann = findAutowiredAnnotation(superCtor);
}
catch (NoSuchMethodException ex) {
// Simply proceed, no equivalent superclass constructor found...
}
}
}
//这儿获取的值不是空,直接进入这个判断
if (ann != null) {
//这个值为空
if (requiredConstructor != null) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructor: " + candidate +
". Found constructor with 'required' Autowired annotation already: " +
requiredConstructor);
}
//这儿的返回的值是true
boolean required = determineRequiredStatus(ann);
if (required) {
//这个时候这个candidates的长度也是空
if (!candidates.isEmpty()) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructors: " + candidates +
". Found constructor with 'required' Autowired annotation: " +
candidate);
}
//存入到这个变量中去
requiredConstructor = candidate;
}
//添加到candidates变量中去
candidates.add(candidate);
}
//由于上面的if执行了,所以这个else if不会执行
else if (candidate.getParameterCount() == 0) {
defaultConstructor = candidate;
}
}
//判断这个值是不是等于空,这儿这个值不为空
if (!candidates.isEmpty()) {
// Add default constructor to list of optional constructors, as fallback.
//这个值不为空,所以这个判断是不会执行的
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));
}
}
//所以往candidateConstructors赋值
candidateConstructors = candidates.toArray(new Constructor<?>[0]);
}
//找到所有的构造函数的长度等于1,同时这个构造函数的参数的长度大于0,这儿不会执行
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
}
//非合成的构造函数的个数等于2,同时primaryConstructor这个值不等于null,这个值只有在kotlin的情况,可能不为空
//默认的构造函数的值不等于空,同时主要的构造函数不包含这个默认的构造函数,这个判断是不会成立的,直接跳过
else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
}
//非合成的构造函数的个数等于1,同时primaryConstructor这个值不等于null,这个值只有在kotlin的情况,可能不为空
//这个时候这个判断也不会成立
else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
candidateConstructors = new Constructor<?>[] {primaryConstructor};
}
//这个判断也不会进,因为前面的判断已经执行了
else {
candidateConstructors = new Constructor<?>[0];
}
//将这个候选构造函数的数组放入到候选构造函数的缓存中
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
}
}
//这个长度就是等于1,直接返回刚才那个找到的构造函数
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
上面的代码走来获取的所有的构造函数然后存入到rawCandidates
变量中去,然后查找调用BeanUtils.findPrimaryConstructor(beanClass);
方法查找主要的构造函数,这个方法只对kotlin的有用,所以默认情况下这个方法的返回值都是为空,所以primaryConstructor
一般的情况下都是为空,然后开始遍历这些的构造函数,查找这些构造函数中不是合成的构造函数的个数,将这个个数存入到nonSyntheticConstructors
变量中去,然后这些方法的上有没有添加@Autowired
注解,如果这个类是cglib的代理的类,就查找它的父类的这个对应的构造方法上有没有添加@Autowired
注解,我们这儿提供的构造方法加了@Autowired的注解,所以这个判断会成立,然后去获取@Autowired注解中的required这个值等于多少,我们这儿提供的是true,所以将这个构造函数赋值给requiredConstructor
变量。然后添加到添加到candidates
集合中去。下面的五个判断,会直接进入第一个if判断,然后判断requiredConstructor
的值是不是等于null,很明显这儿是不等于空的,于是往candidateConstructors
赋值,最后再将这个变量put到candidateConstructorsCache
,由于candidateConstructors
这个变量的长度不等于0,所以返回的是这个默认的构造函数。
这个时候可能有读者会说,如果这个无参的构造函数上面的加的注解是@Autowired(required=false)
,那么结果是怎么样的呢?唯一的区别就是在下面的这个判断中的区别了,具体的代码如下:
if (ann != null) {
if (requiredConstructor != null) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructor: " + candidate +
". Found constructor with 'required' Autowired annotation already: " +
requiredConstructor);
}
//这个时候这个获取的值就是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);
}
//这个值就不会存进去
requiredConstructor = candidate;
}
candidates.add(candidate);
}
//判断这个值是不是等于空,这儿这个值不为空
if (!candidates.isEmpty()) {
// Add default constructor to list of optional constructors, as fallback.
//这个值为空。
if (requiredConstructor == null) {
//这个判断也是等于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));
}
}
//所以往candidateConstructors赋值,这个还是会执行
candidateConstructors = candidates.toArray(new Constructor<?>[0]);
}
所以和加@Autowired的注解的区别没有多大的区别,无非就是requiredConstructor
变量没有赋值,但是最终都是往candidateConstructors
中赋值了,最后都是将这个put到candidateConstructorsCache
这个Map中,最后返回的还是这个构造函数。
这个时候可能又有读者来说,如果这个构造函数有参数,你通读所有的代码你会发现和加没有加参数没有多大关系,所以也是会返回这个构造函数。
总结:有且只有一个构造函数,并且这个构造函数上加了@Autowired注解,而这个注解的required的值不管是true还是false,都是返回这个构造函数
2.3提供一个带参数的构造函数
上面说了一个构造函数的情况,一种是没有@Autowired
注解的无参的构造函数,返回的null,另外一种是加了@Autowired
注解的构造函数,不管构造函数的参数是多少,不管@Autowired
中的required
的值是多少,都会返回这个构造函数,那么一个构造函数,还有一种情况就是有参数的构造函数,但是这个构造函数没有加@Autowired
的注解,具体的代码如下:
package com.ys.beanLife.bean;
import org.springframework.stereotype.Component;
@Component
public class A{
public A(B b) {
}
}
废话不多说还是直接上代码,具体的代码如下:
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
throws BeanCreationException {
//省略处理LookUp注解的方法
// Quick check on the concurrent map first, with minimal locking.
// 这才是本篇博客的重点,去推断构造方法
// 这儿取出来是空的,因为没有往其中put过
// 候选的构造函数
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 {
//从A类中取出所有的构造函数
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);
//用来存加了@Autowired(required=true)注解的构造f方法
Constructor<?> requiredConstructor = null;
//默认的构造函数
Constructor<?> defaultConstructor = null;
//这个方法只对Kotlin有用,正常的情况直接返回null
Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
//不是合成的构造函数的个数
int nonSyntheticConstructors = 0;
//遍历所有的构造函数
for (Constructor<?> candidate : rawCandidates) {
//如果这个构造函数不是合成的,就给nonSyntheticConstructors变量加1,至于什么是合成的函数,笔者前面的博客有讲过
if (!candidate.isSynthetic()) {
nonSyntheticConstructors++;
}
//这个值默认为空,只有在是kotlin的情况可能不为空
else if (primaryConstructor != null) {
continue;
}
//查找这个构造方法中有没有加@Autowired注解,这儿是null
MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
if (ann == null) {
//获取这个类的要使用的类,如果这个类是Cglib的代理的话,就返回的父类,如果没有直接返回对应的类,这儿获取的A.class
Class<?> userClass = ClassUtils.getUserClass(beanClass);
//只有是代理的情况下会执行
if (userClass != beanClass) {
try {
//根据当前遍历的构造函数,获取父类的对应的构造函数
Constructor<?> superCtor =
userClass.getDeclaredConstructor(candidate.getParameterTypes());
//然后查找这个构造函数上是不是加了@Autowired注解
ann = findAutowiredAnnotation(superCtor);
}
catch (NoSuchMethodException ex) {
// Simply proceed, no equivalent superclass constructor found...
}
}
}
//这儿获取的是空,直接跳过
if (ann != null) {
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);
}
requiredConstructor = candidate;
}
candidates.add(candidate);
}
//这个判断也是不会成立的
else if (candidate.getParameterCount() == 0) {
defaultConstructor = candidate;
}
}
//上面的判断没有进,这个判断也是不成立
if (!candidates.isEmpty()) {
// Add default constructor to list of optional constructors, as fallback.
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));
}
}
candidateConstructors = candidates.toArray(new Constructor<?>[0]);
}
//找到所有的构造函数的长度等于1,同时这个构造函数的参数的长度大于0,这个会执行,
//将这个唯一带参的构造函数创建好对应数组存到candidateConstructors中去
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
}
//非合成的构造函数的个数等于2,同时primaryConstructor这个值不等于null,这个值只有在kotlin的情况,可能不为空
//默认的构造函数的值不等于空,同时主要的构造函数不包含这个默认的构造函数,这个判断是不会成立的,直接跳过
else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
}
//非合成的构造函数的个数等于1,同时primaryConstructor这个值不等于null,这个值只有在kotlin的情况,可能不为空
//这个时候这个判断也不会成立
else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
candidateConstructors = new Constructor<?>[] {primaryConstructor};
}
//这个判断也不会进,因为前面的判断已经执行了
else {
candidateConstructors = new Constructor<?>[0];
}
//将这个候选构造函数的数组放入到候选构造函数的缓存中
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
}
}
//这个长度就是等于1,直接返回刚才那个找到的构造函数
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
上面的代码走来获取的所有的构造函数然后存入到rawCandidates
变量中去,然后查找调用BeanUtils.findPrimaryConstructor(beanClass);
方法查找主要的构造函数,这个方法只对kotlin的有用,所以默认情况下这个方法的返回值都是为空,所以primaryConstructor
一般的情况下都是为空,然后开始遍历这些的构造函数,查找这些构造函数中不是合成的构造函数的个数,将这个个数存入到nonSyntheticConstructors
变量中去,然后这些方法的上有没有添加@Autowired
注解,如果这个类是cglib的代理的类,就查找它的父类的这个对应的构造方法上有没有添加@Autowired
注解,我们这儿提供的一个有参的构造函数没有添加@Autowired
的注解,所以第一个判断anno!=0
,这个判断是不成立的,第二个判断,这个构造函数的参数的个数是等于0的,这个判断也是不成立的,于是会走下面的五个判断,只有第二个满足条件,于是创建Constructor
数组将这个值存到candidateConstructors
中,最后将这个值put到candidateConstructorsCache
,最后判断这个candidateConstructorsCache
的长度是不是大于0,如果大于0,直接返回这个candidateConstructorsCache
,很明显这儿是满足条件,于是直接返回这个唯一的构造函数。
总结:提供了一个带参数的构造函数,同时这个构造函数上面没有添加@Autowired注解,这个时候返回的就是这个唯一的构造函数。
2.4多个构造函数(都没有添加@Autowired)
我们这儿提供多个构造函数,具体的例子如下:
package com.ys.beanLife.bean;
import org.springframework.stereotype.Component;
@Component
public class A{
public A() {
}
public A(B b) {
}
public A(C c) {
}
}
我们还是看原来的代码,具体的代码如下:
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
throws BeanCreationException {
//省略处理LookUp注解的方法
// Quick check on the concurrent map first, with minimal locking.
// 这才是本篇博客的重点,去推断构造方法
// 这儿取出来是空的,因为没有往其中put过
// 候选的构造函数
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 {
//从A类中取出所有的构造函数
//这个时候取出来的构造函数如下:
//A()
//A(B b)
//A(C c)
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);
//用来存加了@Autowired(required=true)注解的构造f方法
Constructor<?> requiredConstructor = null;
//默认的构造函数
Constructor<?> defaultConstructor = null;
//这个方法只对Kotlin有用,正常的情况直接返回null
Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
//不是合成的构造函数的个数
int nonSyntheticConstructors = 0;
//遍历所有的构造函数,下面的遍历只有是无参的构造函数会执行其中的代码,其他的时候都不会执行
for (Constructor<?> candidate : rawCandidates) {
//如果这个构造函数不是合成的,就给nonSyntheticConstructors变量加1,至于什么是合成的函数,笔者前面的博客有讲过
if (!candidate.isSynthetic()) {
nonSyntheticConstructors++;
}
//这个值默认为空,只有在是kotlin的情况可能不为空
else if (primaryConstructor != null) {
continue;
}
//查找这个构造方法中有没有加@Autowired注解,这儿是null
MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
if (ann == null) {
//获取这个类的要使用的类,如果这个类是Cglib的代理的话,就返回的父类,如果没有直接返回对应的类,这儿获取的A.class
Class<?> userClass = ClassUtils.getUserClass(beanClass);
//只有是代理的情况下会执行
if (userClass != beanClass) {
try {
//根据当前遍历的构造函数,获取父类的对应的构造函数
Constructor<?> superCtor =
userClass.getDeclaredConstructor(candidate.getParameterTypes());
//然后查找这个构造函数上是不是加了@Autowired注解
ann = findAutowiredAnnotation(superCtor);
}
catch (NoSuchMethodException ex) {
// Simply proceed, no equivalent superclass constructor found...
}
}
}
//这儿获取的是空,直接跳过
if (ann != null) {
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);
}
requiredConstructor = candidate;
}
candidates.add(candidate);
}
//这个判断会成立,只有在第一次遍历无参的构造函数的时候成立
else if (candidate.getParameterCount() == 0) {
defaultConstructor = candidate;
}
}
//上面的判断没有进,这个判断也是不成立
if (!candidates.isEmpty()) {
// Add default constructor to list of optional constructors, as fallback.
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));
}
}
candidateConstructors = candidates.toArray(new Constructor<?>[0]);
}
//找到所有的构造函数的长度等于1,同时这个构造函数的参数的长度大于0,这个判断也不会执行
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
}
//非合成的构造函数的个数等于2,同时primaryConstructor这个值不等于null,这个值只有在kotlin的情况,可能不为空
//默认的构造函数的值不等于空,同时主要的构造函数不包含这个默认的构造函数,这个判断是不会成立的,直接跳过
else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
}
//非合成的构造函数的个数等于1,同时primaryConstructor这个值不等于null,这个值只有在kotlin的情况,可能不为空
//这个时候这个判断也不会成立
else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
candidateConstructors = new Constructor<?>[] {primaryConstructor};
}
//这个判断会执行,因为前面所有判断都没有执行,所以就创建了一个Constructor数组存入到candidateConstructors
else {
candidateConstructors = new Constructor<?>[0];
}
//将这个候选构造函数的数组放入到候选构造函数的缓存中
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
}
}
//这个长度就是等于0,直接返回null
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
上面的代码走来获取的所有的构造函数然后存入到rawCandidates
变量中去,这个时候查找出来的是三个,分别是A()、A(B b)、A(C c),然后查找调用BeanUtils.findPrimaryConstructor(beanClass);
方法查找主要的构造函数,这个方法只对kotlin的有用,所以默认情况下这个方法的返回值都是为空,所以primaryConstructor
一般的情况下都是为空,然后开始遍历这些的构造函数,查找这些构造函数中不是合成的构造函数的个数,将这个个数存入到nonSyntheticConstructors
变量中去,然后判断这些方法的上有没有添加@Autowired
注解,如果这个类是cglib的代理的类,就查找它的父类的这个对应的构造方法上有没有添加@Autowired
注解,我们这儿提供了三个方法,这三个方法中,只有第一个无参的构造函数,才会执行for循环中的if判断的代码,将这个构造函数存到defaultConstructor
变量中去,其他两个构造函数都是不会执行for循环中的if判断中的代码,最后再来看五个if的判断,只有最后一个if判断是成立的,所以这儿又是创建一个空的Constructor
,最后将这个数组存到candidateConstructorsCache
变量中去,最后这个candidateConstructorsCache
变量的长度是等于0,所以返回的是null
可能有笔者会说这儿如果不提供无参的构造函数,会怎么样,无非就是就是defaultConstructor
这个变量没有值,后面的操作还是一样的,返回的还是null
总结:多个构造函数,没有提供@Autowired注解,这个时候返回的就是null
2.5多个构造函数(只有一个构造函数加了@Autowired)
我们这个时候提供多个构造函数,只有一个构造函数上面提交@Autowired
,具体的如下:
package com.ys.beanLife.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class A{
public A() {
}
@Autowired
public A(B b) {
}
public A(C c) {
}
}
我们来看原来的代码,具体的代码如下:
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
throws BeanCreationException {
//省略处理LookUp注解的方法
// Quick check on the concurrent map first, with minimal locking.
// 这才是本篇博客的重点,去推断构造方法
// 这儿取出来是空的,因为没有往其中put过
// 候选的构造函数
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 {
//从A类中取出所有的构造函数
//这个时候取出来的构造函数如下:
//A()
//A(B b) 这个加了@Autowired注解
//A(C c)
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);
//用来存加了@Autowired(required=true)注解的构造f方法
Constructor<?> requiredConstructor = null;
//默认的构造函数
Constructor<?> defaultConstructor = null;
//这个方法只对Kotlin有用,正常的情况直接返回null
Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
//不是合成的构造函数的个数
int nonSyntheticConstructors = 0;
//遍历所有的构造函数,下面的遍历会将默认的无参的构造方法存到defaultConstructor
for (Constructor<?> candidate : rawCandidates) {
//如果这个构造函数不是合成的,就给nonSyntheticConstructors变量加1,至于什么是合成的函数,笔者前面的博客有讲过
if (!candidate.isSynthetic()) {
nonSyntheticConstructors++;
}
//这个值默认为空,只有在是kotlin的情况可能不为空
else if (primaryConstructor != null) {
continue;
}
//查找这个构造方法中有没有加@Autowired注解,这儿是第二个方法的时候不为空
MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
//在这种情况下,返回的值就不是空
if (ann == null) {
//获取这个类的要使用的类,如果这个类是Cglib的代理的话,就返回的父类,如果没有直接返回对应的类,这儿获取的A.class
Class<?> userClass = ClassUtils.getUserClass(beanClass);
//只有是代理的情况下会执行
if (userClass != beanClass) {
try {
//根据当前遍历的构造函数,获取父类的对应的构造函数
Constructor<?> superCtor =
userClass.getDeclaredConstructor(candidate.getParameterTypes());
//然后查找这个构造函数上是不是加了@Autowired注解
ann = findAutowiredAnnotation(superCtor);
}
catch (NoSuchMethodException ex) {
// Simply proceed, no equivalent superclass constructor found...
}
}
}
//第二个构造函数的时候不为空
if (ann != null) {
if (requiredConstructor != null) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructor: " + candidate +
". Found constructor with 'required' Autowired annotation already: " +
requiredConstructor);
}
//这儿获取的值是true
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);
}
//将这个构造函数存到requiredConstructor
requiredConstructor = candidate;
}
//添加到candidates
candidates.add(candidate);
}
//这个判断会成立,只有在第一次遍历无参的构造函数的时候成立
else if (candidate.getParameterCount() == 0) {
defaultConstructor = candidate;
}
}
//这个判断是会进
if (!candidates.isEmpty()) {
// Add default constructor to list of optional constructors, as fallback.
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));
}
}
//取出下标的第一个直接转成数组存到candidateConstructors
candidateConstructors = candidates.toArray(new Constructor<?>[0]);
}
//找到所有的构造函数的长度等于1,同时这个构造函数的参数的长度大于0,这个判断也不会执行
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
}
//非合成的构造函数的个数等于2,同时primaryConstructor这个值不等于null,这个值只有在kotlin的情况,可能不为空
//默认的构造函数的值不等于空,同时主要的构造函数不包含这个默认的构造函数,这个判断是不会成立的,直接跳过
else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
}
//非合成的构造函数的个数等于1,同时primaryConstructor这个值不等于null,这个值只有在kotlin的情况,可能不为空
//这个时候这个判断也不会成立
else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
candidateConstructors = new Constructor<?>[] {primaryConstructor};
}
//这个判断也是不会执行
else {
candidateConstructors = new Constructor<?>[0];
}
//将这个候选构造函数的数组放入到候选构造函数的缓存中
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
}
}
//这个长度就是等于1,直接返回找到的构造函数
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
上面的代码走来获取的所有的构造函数然后存入到rawCandidates
变量中去,这个时候查找出来的是三个,分别是A()、A(B b)这个加了@Autowired
注解、A(C c),然后查找调用BeanUtils.findPrimaryConstructor(beanClass);
方法查找主要的构造函数,这个方法只对kotlin的有用,所以默认情况下这个方法的返回值都是为空,所以primaryConstructor
一般的情况下都是为空,然后开始遍历这些的构造函数,查找这些构造函数中不是合成的构造函数的个数,将这个个数存入到nonSyntheticConstructors
变量中去,然后判断这些方法的上有没有添加@Autowired
注解,如果这个类是cglib的代理的类,就查找它的父类的这个对应的构造方法上有没有添加@Autowired
注解,我们这儿提供了三个方法,这三个方法中,第一次进入循环的是无参的构造函数,就会直接存到defaultConstructor
中去,第二次进入循环,正好这个方法加了@Autowired
的注解,于是获取这个@Autowired
注解中required
的值等于多少,这个值是等于true
,于是将这个构造函数存入到requiredConstructor
最后将这个构造函数存入到candidates
,第三次执行的时候,里面的判断都是不会进入,然后就会执行后面的五个判断,会进入第一个判断,这个时候判断的requiredConstructor
的值是不等于null,所以直接将这个构造函数存到candidateConstructors
,最后将candidateConstructors
变量存入到candidateConstructorsCache
,最后判断candidateConstructorsCache
这个变量的长度是不是大于0,这儿的长度是1,所以直接返回这个构造函数。
可能有读者会说:如果这个加了@Autowired
注解中required
的值等于false
情况是什么样的,这个时候区别就是获取的required
的值等于false
,这个时候就不会将这个构造函数存到requiredConstructor
变量中去,然后还是会添加到candidates
变量中去的,最后看的就是最后五个判断,只有第一个判断的会进,这个时候requiredConstructor
的值等于null,于是将刚才找到的defaultConstructor
添加到candidates
变量中去,最后取出这个candidates
集合中第一个的构造函数组存到candidateConstructors
变量中去,最后将这个变量存到candidateConstructorsCache
,最后判断这个变量长度是不是大于0,很明显这个长度是大于0,等于1,就直接返回这个加@Autowired
的注解的构造函数和无参的构造函数。
总结:多个构造函数,只有一个构造函数上面加了@Autowired的注解,如果这个@Autowired注解中required的值等于true,就会返回这个加了@Autowired注解的构造函数。如果这个@Autowired注解中required的值等于false,并且这个@Autowired的注解没有加到无参的构造函数上,这个时候就会返回加了@Autowired注解的函数和无参的构造函数
2.6多个构造函数,都加了@Autowired,并且required的值等于true
如果多个构造函数,每个构造函数上面都加了@Autowired
注解,并且这个@Autowired
中的required
的值都是true
,具体的代码如下:
package com.ys.beanLife.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class A{
@Autowired
public A() {
}
@Autowired
public A(B b) {
}
@Autowired
public A(C c) {
}
}
我们来看原来的代码,具体的代码如下:
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
throws BeanCreationException {
//省略处理LookUp注解的方法
// Quick check on the concurrent map first, with minimal locking.
// 这才是本篇博客的重点,去推断构造方法
// 这儿取出来是空的,因为没有往其中put过
// 候选的构造函数
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 {
//从A类中取出所有的构造函数
//这个时候取出来的构造函数如下:
//A() 这个加了@Autowired注解
//A(B b) 这个加了@Autowired注解
//A(C c) 这个加了@Autowired注解
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);
//用来存加了@Autowired(required=true)注解的构造f方法
Constructor<?> requiredConstructor = null;
//默认的构造函数
Constructor<?> defaultConstructor = null;
//这个方法只对Kotlin有用,正常的情况直接返回null
Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
//不是合成的构造函数的个数
int nonSyntheticConstructors = 0;
//遍历所有的构造函数,下面的遍历会将默认的无参的构造方法存到defaultConstructor
for (Constructor<?> candidate : rawCandidates) {
//如果这个构造函数不是合成的,就给nonSyntheticConstructors变量加1,至于什么是合成的函数,笔者前面的博客有讲过
if (!candidate.isSynthetic()) {
nonSyntheticConstructors++;
}
//这个值默认为空,只有在是kotlin的情况可能不为空
else if (primaryConstructor != null) {
continue;
}
//查找这个构造方法中有没有加@Autowired注解,不为空
MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
//在这种情况下,返回的值就不是空
if (ann == null) {
//获取这个类的要使用的类,如果这个类是Cglib的代理的话,就返回的父类,如果没有直接返回对应的类,这儿获取的A.class
Class<?> userClass = ClassUtils.getUserClass(beanClass);
//只有是代理的情况下会执行
if (userClass != beanClass) {
try {
//根据当前遍历的构造函数,获取父类的对应的构造函数
Constructor<?> superCtor =
userClass.getDeclaredConstructor(candidate.getParameterTypes());
//然后查找这个构造函数上是不是加了@Autowired注解
ann = findAutowiredAnnotation(superCtor);
}
catch (NoSuchMethodException ex) {
// Simply proceed, no equivalent superclass constructor found...
}
}
}
//不为空
if (ann != null) {
//第一次不成立,第二次就成立了
if (requiredConstructor != null) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructor: " + candidate +
". Found constructor with 'required' Autowired annotation already: " +
requiredConstructor);
}
//这儿获取的值是true
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);
}
//将这个构造函数存到requiredConstructor
requiredConstructor = candidate;
}
//添加到candidates
candidates.add(candidate);
}
//这个判断不会成立
else if (candidate.getParameterCount() == 0) {
defaultConstructor = candidate;
}
}
//这个判断不会进,上面已经报错了
if (!candidates.isEmpty()) {
// Add default constructor to list of optional constructors, as fallback.
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));
}
}
//取出下标的第一个直接转成数组存到candidateConstructors
candidateConstructors = candidates.toArray(new Constructor<?>[0]);
}
//找到所有的构造函数的长度等于1,同时这个构造函数的参数的长度大于0,这个判断也不会执行
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
}
//非合成的构造函数的个数等于2,同时primaryConstructor这个值不等于null,这个值只有在kotlin的情况,可能不为空
//默认的构造函数的值不等于空,同时主要的构造函数不包含这个默认的构造函数,这个判断是不会成立的,直接跳过
else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
}
//非合成的构造函数的个数等于1,同时primaryConstructor这个值不等于null,这个值只有在kotlin的情况,可能不为空
//这个时候这个判断也不会成立
else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
candidateConstructors = new Constructor<?>[] {primaryConstructor};
}
//这个判断也是不会执行
else {
candidateConstructors = new Constructor<?>[0];
}
//将这个候选构造函数的数组放入到候选构造函数的缓存中
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
}
}
//上面已经报错,下面都不会执行
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
上面的代码走来获取的所有的构造函数然后存入到rawCandidates
变量中去,这个时候查找出来的是三个,分别是A()、A(B b)、A(C c),都是加了@Autowired注解,然后查找调用BeanUtils.findPrimaryConstructor(beanClass);
方法查找主要的构造函数,这个方法只对kotlin的有用,所以默认情况下这个方法的返回值都是为空,所以primaryConstructor
一般的情况下都是为空,然后开始遍历这些的构造函数,查找这些构造函数中不是合成的构造函数的个数,将这个个数存入到nonSyntheticConstructors
变量中去,然后判断这些方法的上有没有添加@Autowired
注解,如果这个类是cglib的代理的类,就查找它的父类的这个对应的构造方法上有没有添加@Autowired
注解,我们这儿提供了三个方法,这三个方法中,第一次进入循环的是无参的构造函数,这个方法加了@Autowired
注解,而这个required
的值是true
,所以会存到requiredConstructor
,然后第二次进入的循环的时候,这个时候@Autowired
注解中的required
的值也是true
,于是会判断这个requiredConstructor
这个值是不是等于null,如果等于null的话,就不会报错,但是这儿不等于null,就直接会抛出异常。
总结:多个构造函数,都加了@Autowired注解,并且这些注解中的required 的值是true的话,就直接会抛出异常,如果其中只有一个@Autowired(required=true)的话,也是会直接抛出异常。也就是说,除了所有的@Autowired(required=false)的情况下会不报错,其他组合多个@Autowired都会报错。
2.7多个构造函数,都加了@Autowired,并且required的值都是等于false
如果多个构造函数,每个构造函数上面都加了@Autowired
注解,并且这个@Autowired
中的required
的值都是false
,具体的代码如下:
package com.ys.beanLife.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class A{
@Autowired(required = false)
public A() {
}
@Autowired(required = false)
public A(B b) {
}
@Autowired(required = false)
public A(C c) {
}
}
我们来看原来的代码,具体的代码如下:
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
throws BeanCreationException {
//省略处理LookUp注解的方法
// Quick check on the concurrent map first, with minimal locking.
// 这才是本篇博客的重点,去推断构造方法
// 这儿取出来是空的,因为没有往其中put过
// 候选的构造函数
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 {
//从A类中取出所有的构造函数
//这个时候取出来的构造函数如下:
//A() 这个加了@Autowired(required=false)注解
//A(B b) 这个加了@Autowired(required=false)注解
//A(C c) 这个加了@Autowired(required=false)注解
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);
//用来存加了@Autowired(required=true)注解的构造f方法
Constructor<?> requiredConstructor = null;
//默认的构造函数
Constructor<?> defaultConstructor = null;
//这个方法只对Kotlin有用,正常的情况直接返回null
Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
//不是合成的构造函数的个数
int nonSyntheticConstructors = 0;
//遍历所有的构造函数
for (Constructor<?> candidate : rawCandidates) {
//如果这个构造函数不是合成的,就给nonSyntheticConstructors变量加1,至于什么是合成的函数,笔者前面的博客有讲过
if (!candidate.isSynthetic()) {
nonSyntheticConstructors++;
}
//这个值默认为空,只有在是kotlin的情况可能不为空
else if (primaryConstructor != null) {
continue;
}
//查找这个构造方法中有没有加@Autowired注解,不为空
MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
//在这种情况下,返回的值就不是空
if (ann == null) {
//获取这个类的要使用的类,如果这个类是Cglib的代理的话,就返回的父类,如果没有直接返回对应的类,这儿获取的A.class
Class<?> userClass = ClassUtils.getUserClass(beanClass);
//只有是代理的情况下会执行
if (userClass != beanClass) {
try {
//根据当前遍历的构造函数,获取父类的对应的构造函数
Constructor<?> superCtor =
userClass.getDeclaredConstructor(candidate.getParameterTypes());
//然后查找这个构造函数上是不是加了@Autowired注解
ann = findAutowiredAnnotation(superCtor);
}
catch (NoSuchMethodException ex) {
// Simply proceed, no equivalent superclass constructor found...
}
}
}
//不为空
if (ann != null) {
if (requiredConstructor != null) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructor: " + candidate +
". Found constructor with 'required' Autowired annotation already: " +
requiredConstructor);
}
//这儿获取的值是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);
}
requiredConstructor = candidate;
}
//添加到candidates
candidates.add(candidate);
}
//这个判断不会成立
else if (candidate.getParameterCount() == 0) {
defaultConstructor = candidate;
}
}
//这个判断会进,requiredConstructor的值等于空
if (!candidates.isEmpty()) {
// Add default constructor to list of optional constructors, as fallback.
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));
}
}
//取出下标的第一个直接转成数组存到candidateConstructors,这儿就是所有加了@Autowired(required=false)的构造函数
candidateConstructors = candidates.toArray(new Constructor<?>[0]);
}
//找到所有的构造函数的长度等于1,同时这个构造函数的参数的长度大于0,这个判断也不会执行
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
}
//非合成的构造函数的个数等于2,同时primaryConstructor这个值不等于null,这个值只有在kotlin的情况,可能不为空
//默认的构造函数的值不等于空,同时主要的构造函数不包含这个默认的构造函数,这个判断是不会成立的,直接跳过
else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
}
//非合成的构造函数的个数等于1,同时primaryConstructor这个值不等于null,这个值只有在kotlin的情况,可能不为空
//这个时候这个判断也不会成立
else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
candidateConstructors = new Constructor<?>[] {primaryConstructor};
}
//这个判断也是不会执行
else {
candidateConstructors = new Constructor<?>[0];
}
//将这个候选构造函数的数组放入到候选构造函数的缓存中
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
}
}
//这儿的长度大于0,返回的就是所有加了@Autowired(required=false)的构造函数
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
上面的代码走来获取的所有的构造函数然后存入到rawCandidates
变量中去,这个时候查找出来的是三个,分别是A()、A(B b)、A(C c),都是加了@Autowired(required=false)注解,然后查找调用BeanUtils.findPrimaryConstructor(beanClass);
方法查找主要的构造函数,这个方法只对kotlin的有用,所以默认情况下这个方法的返回值都是为空,所以primaryConstructor
一般的情况下都是为空,然后开始遍历这些的构造函数,查找这些构造函数中不是合成的构造函数的个数,将这个个数存入到nonSyntheticConstructors
变量中去,然后判断这些方法的上有没有添加@Autowired
注解,如果这个类是cglib的代理的类,就查找它的父类的这个对应的构造方法上有没有添加@Autowired
注解,我们这儿提供了三个方法,进入循环的时候,由于都是required
的值等于false
,所以都不会赋值给requiredConstructor
,所以这儿就直接添加到candidates
,最后将这个存入到candidateConstructors
,最后将这个存入到candidateConstructorsCache
,进行返回,也就是返回所有加@Autowired(required=false)
的构造函数。
总结:多个构造函数,每个构造函数都加了@Autowired(required=false)的注解,这个时候返回的就是所有加了这个@Autowired(required=false)的构造函数。
3.推断构造方法总结
- 默认的无参的构造函数(没有加@Autowired注解),返回的是null。
- 有且只有一个构造函数(加了@Autowired注解),不管注解中的required的值是true还是false,都会返回这个构造函数。
- 提供一个带参数的构造函数,同时这个构造函数上面没有添加@Autowired注解,这个时候返回的就是这个唯一的构造函数。
- 多个构造函数,没有提供@Autowired注解,这个时候返回的就是null
- 多个构造函数(只有一个构造函数添加了@Autowired注解),如果这个@Autowired注解中required的值等于true,就会返回这个加了@Autowired注解的构造函数。如果这个@Autowired注解中required的值等于false,并且这个@Autowired的注解没有加到无参的构造函数上,这个时候就会返回加了@Autowired注解的函数和无参的构造函数。
- 多个构造函数,都加了@Autowired注解,并且这些注解中的required的值是true的话,就直接会抛出异常,如果其中只有一个@Autowired(required=true)的话,也是会直接抛出异常。也就是说,除了所有的@Autowired(required=false)的情况下会不报错,其他组合多个@Autowired都会报错。
- 多个构造函数,每个构造函数都加了@Autowired(required=false)的注解,这个时候返回的就是所有加了这个@Autowired(required=false)的构造函数。
4.写在最后
本篇博客,笔者就将Spring中整个推断构造方法给讲完了,后面还有一部分,整个Spring实例化Bean的过程就讲完了,注意,这个时候的实例化出来的Bean,属性还没有填充。