此过程发生在实例化步骤
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#determineConstructorsFromBeanPostProcessors
构造函数扫描
一、构造方法的作用
1.一个构造函数
一般情况下,一个类只有一个构造方法(有参、无参)。
1.只有一个无参构造方法情况,则实例化会使用这个构造方法。
2.只有一个有参构造方法情况。
如果使用AnnotationConfigApplicationContext,则会使用构造函数实例化,根据构造方法参数信息查询bean,将参数传递给构造函数。
如果使用ClassPathXmlApplicationContext,即使用XML方式,可以在XML中手动指定参数值;也可以配置autowire=constructor,让Spring自动去寻找bean做为构造方法参数值
2.多个构造函数选择
Spring4种构造方法的选择规则
1.默认情况下,Spring使用无参构造方法。如果只有一个构造方法,则使用唯一的构造方法。
2.通过指定构造方法的入参个数,选择指定的构造方法。可以通过getBean或者BeanDefinition#getConstructorArgumentValues()指定。
3.可以在指定的构造方法上使用Autowrite注解,选择要使用的构造方法
4.无默认构造方法时,配置autowrite=”constructor”,设置Spring自动选择构造方法及构造方法的入参值(选择入参值最多的构造方法)
autowireConstructor()
- 先检查是否指定了具体的构造方法和构造方法参数值,或者在BeanDefinition中缓存了具体的构造方法或构造方法参数值,如果存在那么则直接使用该构造方法进行实例化
- 如果没有确定的构造方法或构造方法参数值,那么
- 如果没有确定的构造方法,那么则找出类中所有的构造方法
- 如果只有一个无参的构造方法,那么直接使用无参的构造方法进行实例化
- 如果有多个可用的构造方法或者当前Bean需要自动通过构造方法注入
- 根据所指定的构造方法参数值,确定所需要的最少的构造方法参数值的个数
- 对所有的构造方法进行排序,参数个数多的在前面
- 遍历每个构造方法
- 如果不是调用getBean方法时所指定的构造方法参数值,那么则根据构造方法参数类型找值
- 如果时调用getBean方法时所指定的构造方法参数值,就直接利用这些值
- 如果根据当前构造方法找到了对应的构造方法参数值,那么这个构造方法就是可用的,但是不一定这个构造方法就是最佳的,所以这里会涉及到是否有多个构造方法匹配了同样的值,这个时候就会用值和构造方法类型进行匹配程度的打分,找到一个最匹配的
@Bean的创建实例情况
首先,Spring会把@Bean修饰的方法解析成BeanDefinition:
- 如果方法不是static的,那么解析出来的BeanDefinition中:
- factoryBeanName为AppConfig所对应的beanName,比如”appConfig”
- factoryMethodName为对应的方法名,比如”aService”
- factoryClass为AppConfig.class
- 如果方法是static的,那么解析出来的BeanDefinition中:
- factoryBeanName为null
- factoryMethodName为对应的方法名,比如”aService”
- factoryClass也为AppConfig.class
由@Bean生成的BeanDefinition中,有一个重要的属性isFactoryMethodUnique,表示factoryMethod是不是唯一的,在普通情况下@Bean生成的BeanDefinition的isFactoryMethodUnique为true,但是如果出现了方法重复。
比如:
public class AppConfig{
@Bean
public static AService aService(){
return new AService();
}
@Bean
public AService aService(BService bService){
return new AService();
}
}
有两个@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。