0
点赞
收藏
分享

微信扫一扫

Spring源码解析4-spring注解解析过程,ConfigurationClassPostProcessor

booksmg2014 2022-04-05 阅读 52
javaspring

注解利用AnnotationConfigApplicationContext 注册加载Spring上下文

 

构造函数,创建AnnotationConfigApplicationContext实例对象

 

this()—>AnnotationConfigApplicationContext()

 

AnnotatedBeanDefinitionReader(),创建AnnotatedBeanDefinitionReader对象

 

 

创建AnnotatedBeanDefinitionReader后,注册了5个默认的注解处理器

 

有BFPP跟BPP

ConfigurationClassPostProcessor是BFPP、

AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor是BPP

DefaultEventListenerFactory与EventListenerMethodProcessor

 

 

 

 

将获取的AnnotatedGenericBeanDefinition注册到容器中

 

 

然后进行refresh()方法

 

通过调用refresh()的invokeBeanFactoryPostProcessors方法,来调用各种beanFactory增强器

1、ConfigurationClassPostProcessor:

处理@Componen,@ComponentScan,@Bean,@ImportResource,@Import注解。

2、AutowiredAnnotationBeanPostProcessor:处理@Autowired注解和@Value注解。

3、CommonAnnotationBeanPostProcessor: 处理@Resource,这三个增强器是用来解析注解。

 

ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessor,优先级方法是postProcessBeanDefinitionRegistry()

执行ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry()

定位、加载、解析、注册相关注解

 

RootBeanDefinition:Spring内部的BeanDefinition,实现了AbstractBeanDefinition。

GenericBeanDefinition:通过xml配置文件解析出的

AnnotatedGenericBeanDefinition:存储@Configuration注解注释的类,实现了AnnotatedBeanDefinition。

ScannedGenericBeanDefinition:存储@Component、@Service、@Controller等注解注释的类。

spring初始化时,会用GenericBeanDefinition或是ConfigurationClassBeanDefinition(用@Bean注解注释的类)存储用户自定义的Bean,在初始化Bean时,又会将其转换为RootBeanDefinition

processConfigBeanDefinitions()

1.从容器中获取所有已经注册的BeanDefinition的beanName,遍历所有要处理的beanDefinition的名称,筛选被注解修饰的beanDefinition。

 

checkConfigurationClassCandidate()

判断当前BeanDefinition是否是一个配置类,并设置BeanDefinition的属性为了后续调用。

分别判断BeanDefinition是否是AnnotatedGenericBeanDefinition、RootBeanDefinition以及其他获取AnnotationMetadata对象,注解元数据信息

 

根据获取的元数据信息,设置属性

①、如果bean被@Configuration标注,且属性proxyBeanMethods为false(使用代理模式),则将bean定义记为full

②、如果加了@Bean、@Component、@ComponentScan、@Import、@ImportResource注解,则设置为lite

③、如果配置类上被@Order注解标注,则设置BeanDefinition的order属性值

 

1、检测自定义bean名称生成策略

2、环境对象等于空,那么就重新创建新的环境对象

3、实例化ConfigurationClassParser类,并初始化相关的参数,完成配置类的解析工作

 

通过创建的ConfigurationClassParser类,完成配置类的解析工作,解析注解的参数值

 

parse()进行解析

 

根据注解类型进行解析,调用的都是同一个方法

 

 

doProcessConfigurationClass()真正解析方法

递归处理内部类,因为内部类也是一个配置类,配置类上有@configuration注解,该注解继承@Component,if判断为true,调用processMemberClasses方法,递归解析配置类中的内部类

 

processMemberClasses(),找到内部类,判断内部类是不是配置类,将配置类入栈,调用processConfigurationClass方法,因为内部类中还可能包含内部类,所以需要在做循环解析,解析完出栈。

 

递归处理完内部类然后判断@PropertySource注解,

processPropertySource(),配置类上加了@PropertySource注解,那么就解析加载properties文件,并将属性添加到spring上下文中

 

然后判断@ComponentScan或者@ComponentScans注解,并将扫描包下的所有bean转换成填充后的ConfigurationClass

 

解析@ComponentScan和@ComponentScans配置的扫描的包所包含的类,解析注解属性。

比如 basePackages = com.mashibing, 那么在这一步会扫描出这个包及子包下的class,然后将其解析成BeanDefinition

 

 

开始执行扫描,doScan(),扫描basePackage,将符合要求的bean定义全部找出来,遍历所有候选的bean定义,然后开始解析。

 

 

1.处理@Import注解

 

collectImports, 收集@Import注解的类

 

 

检验配置类Import引入的类是否是ImportSelector子类,判断引用选择器是否是DeferredImportSelector接口的实例,如果是则应用选择器将会在所有的配置类都加载完毕后加载,将选择器添加到deferredImportSelectorHandler实例中,预留到所有的配置类加载完成后统一处理自动化配置类

 

 

2.处理@ImportResource注解,导入spring的配置文件。

3.处理加了@Bean注解的方法,将@Bean方法转化为BeanMethod对象,保存再集合中。

retrieveBeanMethodMetadata()

4.处理接口的默认方法实现,从jdk8开始,接口中的方法可以有自己的默认实现,因此如果这个接口的方法加了@Bean注解,也需要被解析。

5.解析父类,如果被解析的配置类继承了某个类,那么配置类的父类也会被进行解析。

所有类的beandifinition信息扫描完,注入ioc容器

springboot自动装载:

beanFactoryPostProsessor中的ConfigurationClassPostProcessor,主要用来处理注解相关的解析工作,包含@Componen,@ComponentScan,@Bean,@ImportResource,@Import,会循环寻找@AutoConfiguration的注解,延时加载,getImport()会调用getCandidateConfigurations,会识别到Spring.facotries的配置文件,完成自动加载

举报

相关推荐

0 条评论