1、这个过程发生在spring工厂refresh方法的invokeBeanFactoryPostProcessors中,取出ConfigurationClassPostProcessor这个BeanFactoryPostProcessors(也是一个BeanDefinitionRegistry类型),调用postProcessBeanDefinitionRegistry方法。

2、ConfigurationClassPostProcessor被添加到spring工厂是发生在AnnotationConfigServletWebServerApplicationContext的构造方法中new AnnotatedBeanDefinitionReader() --->registerAnnotationConfigProcessors() ---> 向spring工厂注册ConfigurationClassPostProcessor

3、postProcessBeanDefinitionRegistry--->processConfigBeanDefinitions方法,获取当前工厂中所有的beanDefinition,检测是否是配置类,是否是配置类是看有没有以下注解:@Configuration、@Component、@ComponentScan、@Import、@ImportResource、以及方法中有没有被@Bean注解的。如果是配置类的话(此时一般来讲,配置类只有SpringApplication.run方法放进来的参数,一般就是配置类),进入while循环,其实一般不会循环而是执行一次,调用parser.parse,再调用this.reader.loadBeanDefinitions(parser.getConfigurationClasses())。

4、parser.parse---processConfigurationClass方法开始会检测OnCondition***,再在循环中对当前类以及所有父类执行doProcessConfigurationClass,再把当前类放入parser的configurationClasses属性中。

5、doProcessConfigurationClass方法中,如果当前类被Component注解了就执行processMemberClasses处理内部类,接下来处理@PropertySource、@ComponentScan、@Import 、@ImportResource、@Bean 注解,

6、processMemberClasses方法处理内部类,还是先看该内部类是不是配置类,如果是的话,执行processConfigurationClass方法。

7、@ComponentScan的处理是扫描指定的包中的类,如果被@Componet注解,执行parse方法。

8、@Import:processImports方法判断:注解中指定的类

     a、如果实现了ImportSelector接口,会被实例化,再判断,如果又实现了DeferredImportSelector接口,这个类会被放到parser的deferredImportSelectorHandler属性中。如果没有,会调用selectImports方法,对返回值再调用processImports方法。

     b、如果实现了ImportBeanDefinitionRegistrar接口,这个类也会被实例化,并被放到configClass的importBeanDefinitionRegistrars属性中。

     c、如果以上的接口都没有实现,那么甚至不判断符不符合配置类的条件,直接被当作配置类调用processConfigurationClass方法。

9、@Bean注解的方法会被封装成BeanMethods,放到parser的beanMethods属性中。

注意:6-9四个步骤是对于配置类和它的所有父类(除了父类以java.***开头的类,也就是rt.jar下面java包里的)

上面的流程中,很多类被放到parser的属性(多是map和set)中了,这些东西在this.reader.loadBeanDefinitions(parser.getConfigurationClasses())中处理:

10、loadBeanDefinitions:其中有方法:registerBeanDefinitionForImportedConfigurationClass; loadBeanDefinitionsForBeanMethod; loadBeanDefinitionsFromRegistrars;

11、registerBeanDefinitionForImportedConfigurationClass:一个配置类,自己是要被收入工厂的。进入本方法之前,会对configClass做一个判断,只有isImported为true,也就是被被别的类导入的ConfigClass才会被处理,回顾之前的代码,只有6和8c两种途径引入的类的isImported为ture。

12、loadBeanDefinitionsFromRegistrars:调用之前已经实例化的8b途径中被导入的类的registerBeanDefinitions方法,向工厂注册类。

13、loadBeanDefinitionsForBeanMethod: 主要是在beanDefinition中设置了factoryMethodName,回顾一下spring源码的getBean--->doCreateBean--->createBeanInstance方法中,在寻找并调用构造方法之前,判断如果factoryMethodName不为空,那么调用instantiateUsingFactoryMethod方法,使用factoryMethod而不是构造方法生成bean。可见factoryMethod和构造方法是一个等级的,那么自动注入在这里也是存在的。

14、8a途径的处理在parse方法的最后,processConfigurationClass的下面,this.deferredImportSelectorHandler.process(),点进去看,最后也是调用的processImports方法,处理返回的一些类。

15、@ImportResource和@PropertySource平时不太能用到,所以略过。

16、a:一个配置类如果没有被@component注解,其内部类以及其父类的内部类不会被当作配置类。但是如果该类是一个被@Component注解了的配置类的父类,其内部类满足配置类的条件后就会被注册,即使该类本身并没有被@Component注解。b:一个类即使满足配置类的条件,但是如果仅仅作为另一个配置类的父类,是不会被注册的。c:@ComponentScan扫描到的、parse方法进入之前放进candidates中的,都要检测该类是不是配置类。但是@Import的8c途径导入的类,不需要检测。