文章目录
一、前言
本文,是本人在阅读源码过程中的一些内容整理和总结。
全文仅代表个人理解和意见,故难免出现错误,如若发现,欢迎指正。十分谢谢。
本文所涉及的文章内容均在 : Spring源码分析:全集整理
关于 :ConfigurationClassPostProcessor
和 AutowiredAnnotationBeanPostProcessor
的详细分析,可以在 Spring源码分析:全集整理 中找到对应的分析文章。
二、正文
2.1 Spring IOC 实现个人感觉最重要的两个类
-
ConfigurationClassPostProcessor
: 完成了类的扫描和配置了的解析 -
AutowiredAnnotationBeanPostProcessor
: 完成了非 Property 的属性的注入
-
ConfigurationClassPostProcessor
是BeanFactoryPostProcessor
子类。postProcessBeanDefinitionRegistry
: 解析所有需要注册的配置类
postProcessBeanFactory
:对Full类型进行代理增强,保证@Bean方法正确语意。 -
AutowiredAnnotationBeanPostProcessor
是BeanPostProcessor
子类,完成了@Autowired、@Value、@Inject
注解的解析注入功能。也就是说AutowiredAnnotationBeanPostProcessor
中才完成了属性的注入。
2.2 Spring什么时候扫描的包路径?
Spring在启动时候会将启动类注册到Spring容器中。在ConfigurationClassPostProcessor
中,会将启动类作为配置类进行解析。由于启动类上面有@ComponentScan
注解,所以在ConfigurationClassParser# doProcessConfigurationClass中
会解析这个注解, 根据解析后的路径通过
his.componentScanParser, parse (componentScan,sourceClass.getMetadata () .getClassName())
进行扫描,注册扫描到的需要注入的类(被@Component
修饰的类)并进行注入,如果有配置类再进行递归的配置类解析。(扫描是在 方法 org.springframework.context. annotation.ClassPathBeanDefinitionScanner#doScan
中进行的扫描,但是我偷懒了没看具体实现)
2.2 ConfigurationClassPostProcessor 的解析流程
. ConfigurationClassPostProcessor
完成了对各种配置类的扫描,并将其引入的bean注册到BeanFactory中。
-
postProcessBeanDefinitionRegistry
方法逻辑(完成了各种配置类的解析和注册) -
获取所有
BeanFactory
中的BeanDefinition
。 -
遍历所有
BeanDefinition
,筛选出full或者lite 配置类,等待下一步处理。Full
规则 :被@Configuration
注解修饰 &&proxyBeanMethods
属性为true (默认为true)Lite
规则:被@Component. @ComponentScan, @Import. @ImportResource
修饰的类或者类中有被@Bean修饰的方法(该方法会被包装成一个 BeanDefinition)
-
遍历所有full 和lite配置类,解析各种注解,对配置类进行进一步的解析(因为Lite的配置类需要二次解析,所以这里主要是二次解析)
- 对
@Component
进行解析:即如果当前配置类被@Component注解修饰,则去解析其内部类(包括静态内部类和非静态内部类)是否是配置类,如果是,递归解析发现的配置类。 - :对
@PropertySource
进行解析:解析出其指定的配置文件内容,并保存到environment 中 - :对
@ComponentScan
注解的解析:获取注解指定路径,进行扫描注册。对新扫描出来的BeanDefinition进行判定是否是配置类,如果是,则递归去解析配置类 - 对
@Import、ImportSelector、ImportBeanDefinitionRegistrar
的解析:因为这三个注解或接口,本质上完成的功能是.一样的,都是引入类。所以在这一部分的处理上只是区分了不同的类型 - 对
@ImportResource
注解的解析:提取出@ImportResource
注解的属性,保存到configClass
的importedResources
属性中 - 对被
@Bean修饰的方法
的解析:提取出@Bean修饰的方法,保存的到configClass
的beanMethods
属性中. - 对接口的默认方法解析:保存的到
configClass
的beanMethods
属性中 - 对父类的解析:如果存在父类,则递归其父类进行解析。
- 对
-
遍历所有的配置类,进行注册
- 处理引入的配置类:将配置类信息封装成
BeanDefinition
,并注册到BeanFactory
- 处理
@Bean修饰的方法
:将@Bean修饰的方法封装成BeanDefinition,并注册到BeanFactory
中 - 处理
@ImportResource
注解引入的资源文件,获取到BeanDefinition并注册。 - 处理
@Import、ImportSelector、ImportBeanDefinitionRegistrar
引入的类,注册到BeanFactory
中。
- 处理引入的配置类:将配置类信息封装成
补充:4.1 中为什么要解析@Component
?
- 因为过滤出来的配置类可能没有被
@Component
修饰,比如仅仅是,可能是Spring硬编码注入或者我们通过编码注入的bean。如果没有使用@Component
注解修饰,就没必要解析其内部类是否是配置类。比如最简单的就是spring.factories
文件中引入的类。可能满足配置类判定,但并没有被@Component
修饰
2.3 AutowiredAnnotationBeanPostProcessor 的解析流程
AutowiredAnnotationBeanPostProcessor
完成@Autowired. @Value、 @Inject
注解的功能, 完成了
Spring的注入
-
determineCandidateConstructors
方法 :筛选出当前bean中能作为构造注入的构造函数列表。用于构造注入- 处理了
@Lookup
注解,将@Lookup
注解标注的方法保存了起来。这一步和构造函数的筛选没有任何关系 - 挑选候选构造函数。简单逻辑就是有注解修饰选注解修饰的构造函数,没有的话使用默认无参构造函数没有无参构造函数,再没有返回null.
- 处理了
-
postProcessProperties
方法 :筛选Bean中需要注入的属性,进行属性注入。用于设置注入和注解注入遍历每个属性,找到被注入注解修饰的属性。保存到currElements
中。遍历每个方法,找到被注入注解修饰的方法, 保存到currElements
中。随后遍历currElements
, 通过resolveDependency
方法将方法或者属性注入(resolveDependency
方法是在populateBean
方法中按照类型注入时调用的方法)这里可以知道,按照顺序遍历,方法的属性在属性的后面,自动注入时,方法的注入结果会把注解属性的注入覆盖掉。
注: Spring注入的方式分为三种 :构造注入、设值注入、注解注入。在AutowiredAnnotationBeanPostProcessor
中处理的实际是设置注入和注解注入。