此过程发生在实例化步骤
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#determineConstructorsFromBeanPostProcessors
构造函数扫描
image.png
image.png

一、构造方法的作用

Spring实例化对象,需要用到构造方法。

1.一个构造函数

一般情况下,一个类只有一个构造方法(有参、无参)。
1.只有一个无参构造方法情况,则实例化会使用这个构造方法。
2.只有一个有参构造方法情况。
如果使用AnnotationConfigApplicationContext,则会使用构造函数实例化,根据构造方法参数信息查询bean,将参数传递给构造函数。
如果使用ClassPathXmlApplicationContext,即使用XML方式,可以在XML中手动指定参数值;也可以配置autowire=constructor,让Spring自动去寻找bean做为构造方法参数值

2.多个构造函数选择

Spring4种构造方法的选择规则
1.默认情况下,Spring使用无参构造方法。如果只有一个构造方法,则使用唯一的构造方法。
2.通过指定构造方法的入参个数,选择指定的构造方法。可以通过getBean或者BeanDefinition#getConstructorArgumentValues()指定。
image.png
3.可以在指定的构造方法上使用Autowrite注解,选择要使用的构造方法
4.无默认构造方法时,配置autowrite=”constructor”,设置Spring自动选择构造方法及构造方法的入参值(选择入参值最多的构造方法)

autowireConstructor()

  1. 先检查是否指定了具体的构造方法和构造方法参数值,或者在BeanDefinition中缓存了具体的构造方法或构造方法参数值,如果存在那么则直接使用该构造方法进行实例化
  2. 如果没有确定的构造方法或构造方法参数值,那么
    1. 如果没有确定的构造方法,那么则找出类中所有的构造方法
    2. 如果只有一个无参的构造方法,那么直接使用无参的构造方法进行实例化
    3. 如果有多个可用的构造方法或者当前Bean需要自动通过构造方法注入
    4. 根据所指定的构造方法参数值,确定所需要的最少的构造方法参数值的个数
    5. 对所有的构造方法进行排序,参数个数多的在前面
    6. 遍历每个构造方法
    7. 如果不是调用getBean方法时所指定的构造方法参数值,那么则根据构造方法参数类型找值
    8. 如果时调用getBean方法时所指定的构造方法参数值,就直接利用这些值
    9. 如果根据当前构造方法找到了对应的构造方法参数值,那么这个构造方法就是可用的,但是不一定这个构造方法就是最佳的,所以这里会涉及到是否有多个构造方法匹配了同样的值,这个时候就会用值和构造方法类型进行匹配程度的打分,找到一个最匹配的

@Bean的创建实例情况

首先,Spring会把@Bean修饰的方法解析成BeanDefinition:

  1. 如果方法不是static的,那么解析出来的BeanDefinition中:
    1. factoryBeanName为AppConfig所对应的beanName,比如”appConfig”
    2. factoryMethodName为对应的方法名,比如”aService”
    3. factoryClass为AppConfig.class
  2. 如果方法是static的,那么解析出来的BeanDefinition中:
    1. factoryBeanName为null
    2. factoryMethodName为对应的方法名,比如”aService”
    3. factoryClass也为AppConfig.class

由@Bean生成的BeanDefinition中,有一个重要的属性isFactoryMethodUnique,表示factoryMethod是不是唯一的,在普通情况下@Bean生成的BeanDefinition的isFactoryMethodUnique为true,但是如果出现了方法重复。
比如:

  1. public class AppConfig{
  2. @Bean
  3. public static AService aService(){
  4. return new AService();
  5. }
  6. @Bean
  7. public AService aService(BService bService){
  8. return new AService();
  9. }
  10. }

有两个@Bean,但只会生成一个aService的Bean,Spring在处理@Bean时,只会生成一个aService的BeanDefinition
1.Spring先解析第一个@Bean,会生成一个BeanDefinition,此时isFactoryMethodUnique为true。
2.解析到第二个@Bean时,会判断出来beanDefinitionMap中已经存在一个aService的BeanDefinition,那么会把之前的这个BeanDefinition的isFactoryMethodUnique修改为false,并且不会生成新的BeanDefinition。
3.后续在根据BeanDefinition创建Bean时,会根据isFactoryMethodUnique来操作。
如果为true,表示当前BeanDefinition只对应一个方法,则用唯一的方法来创建Bean;
如果为false,那就表示当前BeanDefition对应了多个方法,需要和推断构造方法的逻辑一样,去选择用某个方法来创建Bean。

参考:https://note.youdao.com/ynoteshare/index.html?id=d60421c376588a19e20eb8ff7f80115d&type=note&_time=1641304637818