注解利用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的配置文件,完成自动加载