Spring之推断构造方法源码
一、 简介
1. 内容回顾
前面分析了Spring的Bean的生命周期的源码,然后分析了依赖注入源码,以及依赖注入的过程中循环依赖Spring的解决方案。在介绍Bean的生命周期中,我们并没有详细介绍Spring底层是如何真正创建Bean的,其实Spring底层创建Bean和我们new一个对象是一样的,也需要使用到构造函数,这篇文章就详细分析这一部分的源码,这样Bean的生命周期的所有相关的源码就几乎分析完了。
2. Spring推断构造方法
Spring推断构造方法的大致流程如下:
首先创建AService类:
@Component
public class AService {
@Autowired
BService bService;
//空构造方法
public AService(){
System.out.println("AService的无参构造方法");
}
//有参构造方法
public AService(BService bService){
System.out.println("AService的有参构造方法");
this.bService=bService;
}
public void test(){
System.out.println(bService);
}
}
AService有两个构造方法,一个是无参的构造方法,一个是有参的构造方法
创建BService:
@Component
public class BService {
}
然后我们测试一下:
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
// 获取 BoxService bean
AService aService = (AService) applicationContext.getBean("AService");
// 关闭 ApplicationContext
applicationContext.close();
}
}
由输出结果我们可以看出,在创建AService这个Bean时,默认调用了AService的无参数构造方法。现在我们把无参数的构造方法去掉,再次观察结果。
发现此时Spring调用了有参数的构造方法,此时我们再加入一个CService
@Component
public class CService {
}
然后修改AService代码
@Component
public class AService {
@Autowired
BService bService;
@Autowired
CService cService;
// //空构造方法
// public AService(){
// System.out.println("AService的无参构造方法");
// }
//有参构造方法
public AService(BService bService) {
System.out.println("AService的有参构造方法1");
this.bService = bService;
}
//有参构造方法
public AService(CService cService) {
System.out.println("AService的有参构造方法2");
this.cService = cService;
}
public AService(BService bService, CService cService){
System.out.println("AService的有参构造方法3");
this.bService=bService;
this.cService=cService;
}
public void test() {
System.out.println(bService);
}
}
再次测试
发现直接报错了,说明Spring在多个构造方法中没有推断出到底使用哪一个构造方法。
我们可以在我们需要的构造方法上加一个@Autowired
注解告诉Spring我们要使用哪一个构造方法。
@Component
public class AService {
@Autowired
BService bService;
@Autowired
CService cService;
// //空构造方法
// public AService(){
// System.out.println("AService的无参构造方法");
// }
//有参构造方法
public AService(BService bService) {
System.out.println("AService的有参构造方法1");
this.bService = bService;
}
//有参构造方法
public AService(CService cService) {
System.out.println("AService的有参构造方法2");
this.cService = cService;
}
@Autowired
public AService(BService bService, CService cService) {
System.out.println("AService的有参构造方法3");
this.bService = bService;
this.cService = cService;
}
public void test() {
System.out.println(bService);
}
}
同时也可以通过getBean方法来指定我们的构造方法,注意此时AService要改为懒加载的,如果不是懒加载AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
就默认将我们的非懒加载的Bean初始化完了,所以下面测试代码会直接报错,所以需要在AService上加一个@Lazy
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
// 获取 BoxService bean
AService aService = (AService) applicationContext.getBean("AService",new CService());
// 关闭 ApplicationContext
applicationContext.close();
}
}
修改AService
public class AService {
@Autowired
BService bService;
@Autowired
CService cService;
// //空构造方法
// public AService(){
// System.out.println("AService的无参构造方法");
// }
//有参构造方法
public AService(BService bService) {
System.out.println("AService的有参构造方法1");
this.bService = bService;
}
//有参构造方法
public AService(CService cService) {
System.out.println("AService的有参构造方法2");
this.cService = cService;
}
public AService(BService bService, CService cService) {
System.out.println("AService的有参构造方法3");
this.bService = bService;
this.cService = cService;
}
public void test() {
System.out.println(bService);
}
}
现在AService并不是一个Bean,我们修改测试类
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(AppConfig.class);
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(AService.class);
//指定创建bean时,构造方法的入参值
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(new BService());
applicationContext.registerBeanDefinition("AService",beanDefinition);
applicationContext.refresh();
AService aService = (AService) applicationContext.getBean("AService");
applicationContext.close();
}
}
上面我们自己定义了一个BeanDefinition,然后注册到容器中,同样最后也可以拿到创建好的Bean
下面对上面内容总结一下:
- 默认情况使用空构造方法,或使用唯一的那一个有参的构造方法
- 如果指定了构造方法的入参值,通过getBean方法或者BeanDefinition.getConstructorArgumentValues()指定,那就用所匹配的构造方法
- 如果要Spring自己选定构造方法以及构造方法的入参值,使用
autowired="constructor
- 通过
@Autowired
注解指定了某个构造方法,但是值Spring自动来找
注意加@Autowired在构造方法或配置autowired="constructor"在xml配置文件中,这两个是有区别的,前者会指定要用那个构造方法(这个是定死的),然后spring自动找对应的参数值,后者构造方法和参数值都是Spring自己去确定的(默认是选参数最多的构造方法)。
上面介绍了多种指定创建Bean时指定构造方法的多种方式,下面我们就针对这些方式详细分析一下Spring底层时怎么做的。
二、 源码分析
上面内容都是创建Bean的内容,所以我们先进入doCreateBean方法。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// 实例化bean
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// 有可能在本Bean创建之前,就有其他Bean把当前Bean给创建出来了(比如依赖注入过程中)
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 创建Bean实例
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 后置处理合并后的BeanDefinition
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// 为了解决循环依赖提前缓存单例创建工厂
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 循环依赖-添加到三级缓存
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 属性填充
populateBean(beanName, mbd, instanceWrapper);
// 初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
// beanName被哪些bean依赖了,现在发现beanName所对应的bean对象发生了改变,那么则会报错
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
然后实际去创建Bean是在instanceWrapper = createBeanInstance(beanName, mbd, args);
这句代码。
/**
beanName:传入的beanname
RootBeanDefinition:传入的BeanDefinition
Object[] args:getBean传入的参数
**/
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
//拿到当前beandefinition对应的那个类
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());
}
// BeanDefinition中添加了Supplier,则调用Supplier来得到对象
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// @Bean对应的BeanDefinition
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
// 一个原型BeanDefinition,会多次来创建Bean,那么就可以把该BeanDefinition所要使用的构造方法缓存起来,避免每次都进行构造方法推断
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
// autowireNecessary表示有没有必要要进行注入,比如当前BeanDefinition用的是无参构造方法,那么autowireNecessary为false,否则为true,表示需要给构造方法参数注入值
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
// 如果确定了当前BeanDefinition的构造方法,那么看是否需要进行对构造方法进行参数的依赖注入(构造方法注入)
if (autowireNecessary) {
// 方法内会拿到缓存好的构造方法的入参
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 构造方法已经找到了,但是没有参数,那就表示是无参,直接进行实例化
return instantiateBean(beanName, mbd);
}
}
// 如果没有找过构造方法,那么就开始找了
// Candidate constructors for autowiring?
// 提供一个扩展点,可以利用SmartInstantiationAwareBeanPostProcessor来控制用beanClass中的哪些构造方法
// 比如AutowiredAnnotationBeanPostProcessor会把加了@Autowired注解的构造方法找出来,具体看代码实现会更复杂一点
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 如果推断出来了构造方法,则需要给构造方法赋值,也就是给构造方法参数赋值,也就是构造方法注入
// 如果没有推断出来构造方法,但是autowiremode为AUTOWIRE_CONSTRUCTOR,则也可能需要给构造方法赋值,因为不确定是用无参的还是有参的构造方法
// 如果通过BeanDefinition指定了构造方法参数值,那肯定就是要进行构造方法注入了
// 如果调用getBean的时候传入了构造方法参数值,那肯定就是要进行构造方法注入了
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);
}
下面这个代码其实是Spring提供了一个不太有作用的机制
// BeanDefinition中添加了Supplier,则调用Supplier来得到对象
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
Supplier 是 Java 8 引入的函数式接口,用于提供对象的实例。在这里,instanceSupplier 是一个 Supplier<?> 类型的对象,它封装了创建 Bean 实例的逻辑。
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(AppConfig.class);
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(AService.class);
beanDefinition.setInstanceSupplier(new Supplier<Object>() {
@Override
public Object get() {
return new BService();
}
});
applicationContext.registerBeanDefinition("AService",beanDefinition);
applicationContext.refresh();
BService aService = (BService) applicationContext.getBean("AService");
applicationContext.close();
}
}
上面代码本来是想创建一个AService的Bean,我使用Supplier却让里面封装来一个BService。继续回到源码。下面就是创建Bean的核心代码。
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
// autowireNecessary表示有没有必要要进行注入,比如当前BeanDefinition用的是无参构造方法,那么autowireNecessary为false,否则为true,表示需要给构造方法参数注入值
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
上面最核心的是BeanDefitnition提供的两个缓存,第一个是mbd.constructorArgumentLock
,它缓存了BeanDefinition的构造方法,mbd.constructorArgumentsResolved
缓存了构造方法的参数。这两个缓存有什么用呢,考虑一种场景,如果我现在AService是原型bean,我需要多次获取AService对象(使用getBean方法),所以在第一次获取时我需要推断构造方法,然后找到合适的构造方法以及参数,并将其存入到上面的两个缓存中,在以后我多次获取AService对象,我只需要从缓存中拿就可以了,提高了推断构造方法的效率。(注意如果getBean我们没有给额外参数,这个缓存才生效)继续回到源码。
if (resolved) {
// 如果确定了当前BeanDefinition的构造方法,那么看是否需要进行对构造方法进行参数的依赖注入(构造方法注入)
if (autowireNecessary) {
// 方法内会拿到缓存好的构造方法的入参
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 构造方法已经找到了,但是没有参数,那就表示是无参,直接进行实例化
return instantiateBean(beanName, mbd);
}
}
当我们传入的getBean没有提供额外的参数(只提供了beaname),我们就会执行完前面缓存的逻辑,缓存执行完后resolved=true
,所以会进入上面代码,上面代码首先判断autowireNecessary
,如果我们默认构造函数是无参数的autowireNecessary
就会为false,所以就会执行instantiateBean
方法,使用无参数的构造方法初始化(后面再讲这个方法)。如果只true,表示是有参数的构造函数,所以就会执行autowireConstructor
,这个方法很重要,后面的逻辑也会调用,所以后面再讲。继续回到createBeanInstance源码。
// 如果没有找过构造方法,那么就开始找了
// Candidate constructors for autowiring?
// 提供一个扩展点,可以利用SmartInstantiationAwareBeanPostProcessor来控制用beanClass中的哪些构造方法
// 比如AutowiredAnnotationBeanPostProcessor会把加了@Autowired注解的构造方法找出来,具体看代码实现会更复杂一点
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 如果推断出来了构造方法,则需要给构造方法赋值,也就是给构造方法参数赋值,也就是构造方法注入
// 如果没有推断出来构造方法,但是autowiremode为AUTOWIRE_CONSTRUCTOR,则也可能需要给构造方法赋值,因为不确定是用无参的还是有参的构造方法
// 如果通过BeanDefinition指定了构造方法参数值,那肯定就是要进行构造方法注入了
// 如果调用getBean的时候传入了构造方法参数值,那肯定就是要进行构造方法注入了
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);
}
首先上面我们已经讲完了(缓存中缓存了默认构造方法的情况),上面代码就开始执行案例中的复杂情况,即多个构造方法的情况,首先我们需要知道有哪些构造方法是可以用的,这个逻辑的实现就是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;
}
然后调用的核心函数就是bp.determineCandidateConstructors
,可以发现这个方法是AutowiredAnnotationBeanPostProcessor
对象的方法,那为什么要AutowiredAnnotationBeanPostProcessor
这个类来实现找构造函数的逻辑嫩?我们知道这个类是处理@Autowired
注解的,所以这个方法在这个类中实现的逻辑就是找到构造方法上面有@Autowired
注解的。
@Override
@Nullable
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
throws BeanCreationException {
// Let's check for lookup methods here...
if (!this.lookupMethodsChecked.contains(beanName)) {
// 判断beanClass是不是java.开头的类,比如String
if (AnnotationUtils.isCandidateClass(beanClass, Lookup.class)) {
try {
Class<?> targetClass = beanClass;
do {
// 遍历targetClass中的method,查看是否写了@Lookup方法
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Lookup lookup = method.getAnnotation(Lookup.class);
if (lookup != null) {
Assert.state(this.beanFactory != null, "No BeanFactory available");
// 将当前method封装成LookupOverride并设置到BeanDefinition的methodOverrides中
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);
}
//判断我之前有没有找过,如果找过就可以从缓存中直接拿到
Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
if (candidateConstructors == null) {
//如果没有找过,就开始第一次寻找(这里访问里公共资源,所以需要加锁保证线程安全)
synchronized (this.candidateConstructorsCache) {
//这里就是DCL机制
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;
// kotlin相关,不用管
Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
int nonSyntheticConstructors = 0;
// 遍历找到的每个构造方法
for (Constructor<?> candidate : rawCandidates) {
if (!candidate.isSynthetic()) {
// 记录一下普通的构造方法
nonSyntheticConstructors++;
}
else if (primaryConstructor != null) {
continue;
}
// 当前遍历的构造方法是否写了@Autowired
MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
//如果没有找到加@Autowired注解的构造函数,如果这个类是代理类就找被代理对象的构造方法上面有没有@Autowired注解
if (ann == null) {
// 如果beanClass是代理类,则得到被代理的类的类型
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...
}
}
}
// 当前构造方法上加了@Autowired
if (ann != null) {
// 整个类中如果有一个required为true的构造方法,那就不能有其他的加了@Autowired的构造方法
if (requiredConstructor != null) {
//requiredConstructor != null说明前面遍历到的构造方法有一个加了@Autowire(require=true),由于整个类只能存在一个require=true,所以会报错
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的方法
}
//如果当前类没有@Autowire注解,且参数个数为0,说明当前类有无参构造方法,spring就会使用这个无参构造方法作为默认的初始化构造方法
else if (candidate.getParameterCount() == 0) {
// 记录唯一一个无参的构造方法
defaultConstructor = candidate;
}
// 有可能存在有参、并且没有添加@Autowired的构造方法
}
if (!candidates.isEmpty()) {
// 如果不存在一个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]};
}
// primaryConstructor不用管
else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
}
// primaryConstructor不用管
else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
candidateConstructors = new Constructor<?>[] {primaryConstructor};
}
else {
// 如果有多个有参、并且没有添加@Autowired的构造方法,是会返回空的
candidateConstructors = new Constructor<?>[0];
}
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
}
}
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
上面的方法的流程我可以总结为下面的图:
回到createBeanInstance
方法
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 如果推断出来了构造方法,则需要给构造方法赋值,也就是给构造方法参数赋值,也就是构造方法注入
// 如果没有推断出来构造方法,但是autowiremode为AUTOWIRE_CONSTRUCTOR,则也可能需要给构造方法赋值,因为不确定是用无参的还是有参的构造方法
// 如果通过BeanDefinition指定了构造方法参数值,那肯定就是要进行构造方法注入了
// 如果调用getBean的时候传入了构造方法参数值,那肯定就是要进行构造方法注入了
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);
}
ctors
存储了前逻辑判断出来的构造方法,然后进入if判断,如果ctors不为空且满足if的任意一个条件就调用autowireConstructor
方法,否则就直接调用instantiateBean
使用无参的构造方法实例化。
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
try {
Object beanInstance;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged(
(PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
getAccessControlContext());
}
else {
// 默认是CglibSubclassingInstantiationStrategy
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
}
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
上面创建Bean的核心代码是beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
,这里就是使用的Cglib动态代理技术来创建Bean实例。
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
// 判断当前BeanDefinition对应的beanClass中是否存在@Lookup的方法
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class<?> clazz = bd.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(
(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
}
else {
//这句代码就获得了当前类的无参数构造方法
constructorToUse = clazz.getDeclaredConstructor();
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
// 如果存在@Lookup,则会生成一个代理对象
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
然后继续调用BeanUtils.instantiateClass(constructorToUse);
传入的参数就是前面获得的无参数的构造方法。
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
Assert.notNull(ctor, "Constructor must not be null");
try {
ReflectionUtils.makeAccessible(ctor);
if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {
return KotlinDelegate.instantiateClass(ctor, args);
}
else {
Class<?>[] parameterTypes = ctor.getParameterTypes();
Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters");
Object[] argsWithDefaultValues = new Object[args.length];
for (int i = 0 ; i < args.length; i++) {
if (args[i] == null) {
Class<?> parameterType = parameterTypes[i];
argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null);
}
else {
argsWithDefaultValues[i] = args[i];
}
}
//根据构造放阿福进行真正的实例化
return ctor.newInstance(argsWithDefaultValues);
}
}
catch (InstantiationException ex) {
throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
}
catch (IllegalAccessException ex) {
throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);
}
catch (IllegalArgumentException ex) {
throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);
}
catch (InvocationTargetException ex) {
throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());
}
}
上面代码就完成了使用无参构造方法的实例化,继续回到createBeanInstance
。如果我们返回来的构造方法集合ctors
不为空,就会执行autowireConstructor
这一核心方法,执行真正的构造方法推断逻辑。
/**
beanName:bean的名称
mbd:BeanDefitnition
chosenCtors:可行的构造函数候选集合(前面的逻辑得出来的)
explicitArgs:getBean方法额外的参数
**/
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
//初始化用于存储构造函数和参数信息的变量
Constructor<?> constructorToUse = null;
ArgumentsHolder argsHolderToUse = null;
//这个数组记录了构造方法所需要的参数
Object[] argsToUse = null;
// 如果getBean()传入了args,那构造方法要用的入参就直接确定好了
if (explicitArgs != null) {
//getBean方法传了,Spring就不需要自己推断了,直接使用getBean传入的即可
argsToUse = explicitArgs;
}
else {
//如果getbean没有指定构造方法的参数,如果没有传入参数,则尝试从缓存中获取构造函数和参数信息。如果缓存中有,直接使用;否则,调用 resolvePreparedArguments 进行解析。
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
//从缓存中拿(这个缓存前面有说明过)
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
// Found a cached constructor...
//如果缓存中有构造方法的参数值,从缓存中获取构造方法的参数值
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
if (argsToResolve != null) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
}
}
// 如果没有确定要使用的构造方法,或者确定了构造方法但是所要传入的参数值没有确定
if (constructorToUse == null || argsToUse == null) {
// Take specified constructors, if any.
// 如果没有指定构造方法,那就获取beanClass中的所有构造方法所谓候选者
Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
//如果我们没有手动指定构造方法,就获取当前bean得全部构造方法
Class<?> beanClass = mbd.getBeanClass();
try {
candidates = (mbd.isNonPublicAccessAllowed() ?
beanClass.getDeclaredConstructors() : beanClass.getConstructors());
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
}
}
// 如果只有一个候选构造方法,并且没有指定所要使用的构造方法参数值,并且该构造方法是无参的,那就直接用这个无参构造方法进行实例化了
if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
Constructor<?> uniqueCandidate = candidates[0];
if (uniqueCandidate.getParameterCount() == 0) {
synchronized (mbd.constructorArgumentLock) {
//将当前的无参数的构造方法记录到缓存中下车就可以直接从缓存中拿(前面讲过这段代码逻辑)
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
//直接调用instantiate进行无参构造方法的实例化
bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}
// autowiring表示是否支持自动注入,如果是true,那么我们没指定的参数spring会帮我们自动注入
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
ConstructorArgumentValues resolvedValues = null;
// 确定要选择的构造方法的参数个数的最小值,后续判断候选构造方法的参数个数如果小于minNrOfArgs,则直接pass掉
int minNrOfArgs;
if (explicitArgs != null) {
// 如果直接传了构造方法参数值,那么所用的构造方法的参数个数肯定不能少于
minNrOfArgs = explicitArgs.length;
}
else {
// 如果通过BeanDefinition传了构造方法参数值,因为有可能是通过下标指定了,比如0位置的值,2位置的值,虽然只指定了2个值,但是构造方法的参数个数至少得是3个
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
// 处理RuntimeBeanReference
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
// 对候选构造方法进行排序,public的方法排在最前面,都是public的情况下参数个数越多越靠前
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Constructor<?>> ambiguousConstructors = null;
Deque<UnsatisfiedDependencyException> causes = null;
// 遍历每个候选构造方法,进行筛选
for (Constructor<?> candidate : candidates) {
// 参数个数
int parameterCount = candidate.getParameterCount();
// 本次遍历时,之前已经选出来了所要用的构造方法和入参对象,并且入参对象个数比当前遍历到的这个构造方法的参数个数多,则不用再遍历,退出循环
if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
// Already found greedy constructor that can be satisfied ->
// do not look any further, there are only less greedy constructors left.
break;
}
// 如果参数个数小于所要求的参数个数,则遍历下一个,这里考虑的是同时存在public和非public的构造方法
if (parameterCount < minNrOfArgs) {
continue;
}
ArgumentsHolder argsHolder;
Class<?>[] paramTypes = candidate.getParameterTypes();
// 没有通过getBean()指定构造方法参数值
if (resolvedValues != null) {
try {
// 如果在构造方法上使用了@ConstructorProperties,那么就直接取定义的值作为构造方法的参数名
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
// 获取构造方法参数名
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
}
// 根据参数类型、参数名找到对应的bean对象
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 ArrayDeque<>(1);
}
causes.add(ex);
continue;
}
}
else {
// Explicit arguments given -> arguments length must match exactly.
// 在调getBean方法时传入了参数值,那就表示只能用对应参数个数的构造方法
if (parameterCount != explicitArgs.length) {
continue;
}
// 不用再去BeanFactory中查找bean对象了,已经有了,同时当前正在遍历的构造方法就是可用的构造方法
argsHolder = new ArgumentsHolder(explicitArgs);
}
// 当前遍历的构造方法所需要的入参对象都找到了,根据参数类型和找到的参数对象计算出来一个匹配值,值越小越匹配
// Lenient表示宽松模式
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);
}
}
// 遍历结束 x
// 如果没有可用的构造方法,就取记录的最后一个异常并抛出
if (constructorToUse == null) {
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Could not resolve matching constructor on bean class [" + mbd.getBeanClassName() + "] " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
}
// 如果有可用的构造方法,但是有多个
else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous constructor matches found on bean class [" + mbd.getBeanClassName() + "] " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousConstructors);
}
// 如果没有通过getBean方法传入参数,并且找到了构造方法以及要用的入参对象则缓存
if (explicitArgs == null && argsHolderToUse != null) {
argsHolderToUse.storeCache(mbd, constructorToUse);
}
}
Assert.state(argsToUse != null, "Unresolved constructor arguments");
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
}
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
会根据参数名字和类型去容器中找bean对象。
private ArgumentsHolder createArgumentArray(
String beanName, RootBeanDefinition mbd, @Nullable ConstructorArgumentValues resolvedValues,
BeanWrapper bw, Class<?>[] paramTypes, @Nullable String[] paramNames, Executable executable,
boolean autowiring, boolean fallback) throws UnsatisfiedDependencyException {
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<>(paramTypes.length);
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
// 遍历构造方法的参数类型
for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
// 拿到具体的参数类型和参数名
Class<?> paramType = paramTypes[paramIndex];
String paramName = (paramNames != null ? paramNames[paramIndex] : "");
// Try to find matching constructor argument value, either indexed or generic.
ConstructorArgumentValues.ValueHolder valueHolder = null;
// 如果在BeanDefinition中指定了构造方法参数值,则拿到具体的对象
if (resolvedValues != null) {
valueHolder = resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
// If we couldn't find a direct match and are not supposed to autowire,
// let's try the next generic, untyped argument value as fallback:
// it could match after type conversion (for example, String -> int).
if (valueHolder == null && (!autowiring || paramTypes.length == resolvedValues.getArgumentCount())) {
valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
}
}
if (valueHolder != null) {
// We found a potential match - let's give it a try.
// Do not consider the same value definition multiple times!
usedValueHolders.add(valueHolder);
Object originalValue = valueHolder.getValue();
Object convertedValue;
if (valueHolder.isConverted()) {
convertedValue = valueHolder.getConvertedValue();
args.preparedArguments[paramIndex] = convertedValue;
}
else {
// 如果需要进行类型转化,则转化
MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
try {
convertedValue = converter.convertIfNecessary(originalValue, paramType, methodParam);
}
catch (TypeMismatchException ex) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
"Could not convert argument value of type [" +
ObjectUtils.nullSafeClassName(valueHolder.getValue()) +
"] to required type [" + paramType.getName() + "]: " + ex.getMessage());
}
Object sourceHolder = valueHolder.getSource();
if (sourceHolder instanceof ConstructorArgumentValues.ValueHolder) {
Object sourceValue = ((ConstructorArgumentValues.ValueHolder) sourceHolder).getValue();
args.resolveNecessary = true;
args.preparedArguments[paramIndex] = sourceValue;
}
}
// 当前所遍历的参数所对应的参数值
args.arguments[paramIndex] = convertedValue;
args.rawArguments[paramIndex] = originalValue;
}
else {
MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
// No explicit match found: we're either supposed to autowire or
// have to fail creating an argument array for the given constructor.
if (!autowiring) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
"Ambiguous argument values for parameter of type [" + paramType.getName() +
"] - did you specify the correct bean references as arguments?");
}
try {
// 根据方法参数类型和名字从BeanFactory中匹配Bean对象
Object autowiredArgument = resolveAutowiredArgument(
methodParam, beanName, autowiredBeanNames, converter, fallback);
// 当前所遍历的参数所对应的参数值
args.rawArguments[paramIndex] = autowiredArgument;
args.arguments[paramIndex] = autowiredArgument;
args.preparedArguments[paramIndex] = autowiredArgumentMarker;
args.resolveNecessary = true;
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), ex);
}
}
}
for (String autowiredBeanName : autowiredBeanNames) {
this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Autowiring by type from bean name '" + beanName +
"' via " + (executable instanceof Constructor ? "constructor" : "factory method") +
" to bean named '" + autowiredBeanName + "'");
}
}
return args;
}
上面就是解析某个构造函数的参数。在解析的过程中,它会拿用户传入的构造方法参数值与该构造方法的参数值进行比较,if (!autowiring) {
标记来判断,对于缺少的参数是否可以允许spring来自动注入,底层用的找bean得代码和依赖注入那一套一样。继续回到autowireConstructor
方法。
for (Constructor<?> candidate : candidates) {
// 参数个数
int parameterCount = candidate.getParameterCount();
// 本次遍历时,之前已经选出来了所要用的构造方法和入参对象,并且入参对象个数比当前遍历到的这个构造方法的参数个数多,则不用再遍历,退出循环
if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
// Already found greedy constructor that can be satisfied ->
// do not look any further, there are only less greedy constructors left.
break;
}
// 如果参数个数小于所要求的参数个数,则遍历下一个,这里考虑的是同时存在public和非public的构造方法
if (parameterCount < minNrOfArgs) {
continue;
}
ArgumentsHolder argsHolder;
Class<?>[] paramTypes = candidate.getParameterTypes();
// 没有通过getBean()指定构造方法参数值
if (resolvedValues != null) {
try {
// 如果在构造方法上使用了@ConstructorProperties,那么就直接取定义的值作为构造方法的参数名
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
// 获取构造方法参数名
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
}
// 根据参数类型、参数名找到对应的bean对象
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 ArrayDeque<>(1);
}
causes.add(ex);
continue;
}
}
else {
// Explicit arguments given -> arguments length must match exactly.
// 在调getBean方法时传入了参数值,那就表示只能用对应参数个数的构造方法
if (parameterCount != explicitArgs.length) {
continue;
}
// 不用再去BeanFactory中查找bean对象了,已经有了,同时当前正在遍历的构造方法就是可用的构造方法
argsHolder = new ArgumentsHolder(explicitArgs);
}
上面的逻辑就是遍历每一个候选的构造方法,如果没有在getbean方法中指定参数值就会if (resolvedValues != null) {
逻辑,否则执行下面代码:
// Explicit arguments given -> arguments length must match exactly.
// 在调getBean方法时传入了参数值,那就表示只能用对应参数个数的构造方法
if (parameterCount != explicitArgs.length) {
continue;
}
// 不用再去BeanFactory中查找bean对象了,已经有了,同时当前正在遍历的构造方法就是可用的构造方法
argsHolder = new ArgumentsHolder(explicitArgs);
上面代码如果当前构造函数的参数和传入的个数相同,就直接用当前的构造函数,然后参数值就是我们传入的参数。然后执行后面的逻辑:
// 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);
}
}
如果我们有多个构造函数匹配,它会根据匹配度计算最合适的那一个构造函数。如果有分数相同的就会记录到(且不是严格模式)ambiguousConstructors
这个集合中。继续:
假设bean的类型为A,A的父类是B,B的父类是C,同时A实现了接口D 如果构造方法的参数类型为 A,那么完全匹配,得分为0 如果构造方法的参数类型为B,那么得分为2 如果构造方法的参数类型为 C,那么得分为4 如果构造方法的参数类型为D,那么得分为1。所以,我们可以发现,越匹配分数越低。
//如果有多个匹配度相同的构造函数,它会使用最先匹配的那一个,作为本次要初始化的构造函数
// 如果没有通过getBean方法传入参数,并且找到了构造方法以及要用的入参对象则缓存
if (explicitArgs == null && argsHolderToUse != null) {
argsHolderToUse.storeCache(mbd, constructorToUse);
}
}
最后使用选定的构造方法和参数初始化bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!