推断构造方法

@Configuration注解

    如果一个bean增加了@Configuration注解,得到的就是一个代理对象
    增加了@Configuration的配置类,加了@Bean注解的方法,如果不是spring自身执行的话,就走代理,会直接根据beanFactory从单例池中去查找,否则执行bean的正常创建。这两个是否是同一个对象?是的。

推断构造方法

@Autowired也可以声明再参数前面,不过目前spring只在junit测试中使用了,暂时不支持。

推断构造方法:
AbstractAutowireCapableBeanFactory.

1)applicationContext.getBean(UserService.class,args),参数args是用来推断构造方法的。
2)一个bean有一个无参的构造方法,也有一个有参数的构造方法,默认调用的是无参的构造方法,如果想默认走有参的构造方法,可以再有参的构造方法上增加一个@Autowired注解
3)如果有多个构造方法都是有@Autowired注解的有参构造方法,会报错
4)构造方法是在BeanPostprocessorBeanFactory中查找到的
5)如果只有一个无参的构造方法,查找构造方法时,会返回空,最后使用无参的构造方法创建对象。
6)如果有构造方法了,没有指定值,那就先根据类型再根据名称查找值。如果制定了值,可能会有类型转换。
7)多个构造方法比较时,权重小的优先级高

1)查找到所有的构造方法
    会遍历父类去查找
2)遍历每个构造方法,是否有@Autowired注解的构造方法
    没有:是否是无参的,defaultConstruct
    有:required属性是true,标记为requiredConstructor,加到构造方法candidates集合中。
3)遍历结束后,candidates是否为空,
    为空:
        判断rawCandidates(原始的构造方法)的大小是否等于1,标示是否是只有一个构造方法,如果是就返回唯一的构造方法,否则就返回空数组。
    不为空:
        只存在一个required为true的,把这个构造方法返回
        多个required为false的,如果也有无参的,把无参的也加入到candidates返回
        这里的返回结果要么是只有一个required为true的构造方法, 要么就是required为false的和无参的构造方法(如果又无参构造方法的话)
4)如果返回的构造方法有多个就进行构造方法推断
    autowireConstructor(beanName,mbd,Constructor[],Object[])
    下面两种情况需要推断:
        (1)通过上面的逻辑找到了多个的时候
        (2)AUTOWIRE_CONSTRUCTOR
    通过getBean()方法制定了构造方法
    没有通过getBean()方法制定了构造方法
        从缓存中获取构造方法和构造方法参数值
            有的话就进行
    如果构造方法为null,或待使用构造方法的参数为null        
    如果只有一个构造方法,并且beandefinition中没有制定构造方法参数值,需要判断是不是无参构造方法,如果是则可以使用无参构造方法进行实例化
        把找到的参数值进行缓存,并设置已经找到了构造参数的标志为true
    如果指定了多个构造方法,
    按照构造方法参数个数进行排序,参数多的在前面
    
总结:两大步骤:
    1)找出候选的构造方法
    2)推断使用哪个构造方法
        (1)参数最多的构造方法排序后在最前面,找到就使用
        (2)两个构造方法个数一样,再根据找到的值和类型再去算出一个权重值,权重小的优先使用
如何计算权重?


1查找构造函数:
    返回的结果:
         1)返回的一个带有@autowired(required=true)注解的
         2)返回多个带有@autowired(required=false)注解+无参的构造函数
         3)返回一个有参的构造函数
            只有一个有参的构造函数
         4)返回一个null:
            (1)只有一个无参的构造函数
            (2)一个无参的构造函数,多个有参的构造函数(没有autowired注解)
            (3)个有参的构造函数(没有autowired注解)
2 第一步返回的结果  或者 autowired_constructor     
            也有筛选过滤:
                1)参数多的在前面,
                2)按照上面的顺序遍历构造方法,找参数的额值
                    先根据类型找bean,
                        可能找到多个,如果有多个,再根据名称找
                    如果各个参数都能找到值,而且下一个的构造方法比当前的参数少,就使用当前的构造方法。
                    如果有一个找不到就继续遍历
                    
                    如果找到多个参数相同,而且根据参数都能找到bean的构造方法,这个时候需要比较权重:
                        参数类型和找到的bean的类型相同的话,分数更低
                        非宽松模式下会忽略每个参数值的类型和找到的bean的类型的距离,只要是父子关系距离是一样的(权重值一样)
                        宽松模式下找到了两个参数相同,权重也一样的构造方法,不会报错,费宽松模式下这种情况会报错
                        如何计算分数:
                            类型相同,分是0,如果是一层父子关系就+2,如果是接口和实现的关系,就+1。
                    

你可能感兴趣的:(spring源码解析)