解析Spring确定构造方法的过程
文章目录
- 解析Spring确定构造方法的过程
- 前言
- 一、三个普通构造函数解析过程
- 二、加@Autowired 和 只有一个有参构造函数解析过程
- 总结
前言
每次都是从关键代码进行定位解析,希望大家对Spring源码有一定的了解再看,本篇主要解析determineConstructorsFromBeanPostProcessors(beanClass, beanName);
一、三个普通构造函数解析过程
类:AbstractAutowireCapableBeanFactory 方法:createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
有一个A类 B类(类上加了@Component ) C类(类上加了@Component ) 如下图:
开始解析 定位到关键代码 并进入
这里只有AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors的方法有实现,如下图所示:
继续往下看,会执行到这个else if 并赋值 因为是循环所有的构造 所以这是第一个无参构造,其它则进不了这个赋值过程
循环完成之后 代码如下 判断candidates 里面是否已经有了Constructor方法 只有在@Autowired时才会有值
继续流程 第一个红框代表只定义了一个有参的构造函数 ;第二个 普遍情况;第三个红框就返回对应的内容 一般返回null 或者 有值得构造列表
回到之前得主流程
因为返回null,并其它配置未配置过,所以会走第二个框得逻辑
好了 这个就解析完了
二、加@Autowired 和 只有一个有参构造函数解析过程
其实在第一步推断出来得都是存在构造函数得列表,代码自己进去看看 直接开始解析此行代码下面的代码
autowireConstructor(beanName, mbd, ctors, null) 很麻烦 阅读后 后面的几种方法 也可以迎刃而解,所以这是重点方法; 这里面比较重要的点就是是否设置了宽松模式 以及排序 以及计算构造方法差值等 定位到关键代码,关键代码上方的代码都是赋值校验及缓存等;
首先是排序,根据是否为public 及 里面的参数个数进行决定,代码如下:
继续往下定位到核心代码,这里会循环拿到每个参数的值 是否可赋值 可赋值的在Spring中拿出来(未创建的走创建流程既getBean),如果拿不到抛异常 跳过此构造函数,如下图
第一个框是计算差异值的 受接口 父类的影响 第二个框第一个构造函数会进入,第三个只是为宽松模式做提前铺垫的,如果不是宽松模式,下方会有校验 进行报错。所以综上所述 排完序的第一个构造函数很有可能将会成为确定的构造函数,但也有例外比如第一个构造函数有个接口作为参数,则不确定性就会增大 所以差异值也会变大,看第二个框 比较 谁小 谁有优势,所以在宽松模式 代码如下第二张图
从上图第一个框就可以看出 Spring作者考虑的很周全,应对特殊情况的代码,这里大家能想到应对那种情况的吗,欢迎评论区留言
总结
autowireConstructor(beanName, mbd, ctors, null) 里面代码还是比较重要的