spring boot启动的时候会创建一个注解配置嵌入式web应用上下文AnnotationConfigEmbeddedWebApplicationContext
,在实例化这个ApplicationContext
时,首先会先实例化它的父类GenericApplicationContext
(在父类的构造方法中初始化一个BeanFactory
),然后回到子类的构造方法中初始化注解bean定义阅读器AnnotatedBeanDefinitionReader
和类路径bean定义扫描器ClassPathBeanDefinitionScanner
.
在生成阅读器对象Reader
的时候会把所有与注解配置相关的后处理器Processor
注册到IOC容器当中 [重点1],在这之前还会初始化AnnotationAwareOrderComparator
(处理@Order
和@Priority
注解,还有Ordered
接口)和ContextAnnotationAutowireCandidateResolver
(处理懒加载注解@Lazy
).
类路径bean定义扫描器通过includeFilters
判断需要扫描的情况和通过excludeFilter
判断不扫描的情况(两者都是链表LinkedList
).而在构造函数中(刚创建)只会会注册对@Component
和@ManagedBean
注解的扫描.最后会设置资源加载器ResourceLoader
接着在BeanDefinitionLoader
(会新建它自己的多个阅读器和扫描器,外观模式)的load()
方法中会开始一次对bean定义的加载().它定义的扫描器不扫描用户定义的spring boot启动类,但它却只注册用户定义的spring boot启动类.
值得注意的是扫描到的Bean的注解解析,是在注册bean的时候发生的.还有spring中的元数据`Metadata`一般指的是注解`Annotation
上面的结束后,接下来就进入熟悉的spring初始化方法refresh()
中了
因为spring boot使用的是通用应用上下文GenericApplicationContext
不像AbstractRefreshableApplicationContext
,所以它的bean工厂的创建和bean定义的加载不在refreshBeanFactory()
方法完成,而是在通用应用上下文的构造方法里创建.
prepareBeanFactory()
方法仍然是配置应用上下文感知后处理器ApplicationContextAwareProcessor
(重要)和其他一些东西.
这里也有一个要注意的,那就是bean工厂后处理器`BeanFactoryPostProcessor`和bean处理器`BeanPostProcessor`的区别:
前者是`AbstractApplicationContext`附加的,它本质也是个bean.后者是`AbstractBeanFactory`所持有的(在实例化bean是会回调所有的Bean后处理器)
在invokeBeanFactoryPostProcessors()
中会执行之前注册的后处理器.首先他会调用所有处理器的postProcessBeanDefinitionRegistry()
方法先把所有bean注册好,接着再调用其他处理方法.下面主要说一下几个重要的处理器.
ConfigurationClassPostProcessor
配置类处理器用于处理@Configuration
注解,而在它的postProcessBeanDefinitionRegistry()
方法首先处理的是用户定义的spring boot启动类(上面说过它的加载,@SpringBootApplication
继承了@Configuration
),在这里首先会用配置类解析器ConfigurationClassParser
解析目前唯一一个配置类(通常是webApplication
).
在解析的过程中,因为@SpringBootApplication
同时继承@ComponentScan
注解,所以会触发ComponentScanParser
以用户定义的spring boot启动类所在包为basePackage
进行扫描并注册 注解配置方式的bean (如spring MVC那些注解配置的类).然后判断加载的bean是否是配置类@Configuration
,是则递归调用parse
方法解析 [重点2].
当然parse()
方法还会解析很多其他注解,如@Import
,@ImportResource
,@Bean
,@PropertySource
等.注意@Bean
注解修饰的方法配置的bean定义不是在这里生成的,也不会在这里注册到IOC容器,这里只是做一些配置上的初始化(解析parse()
方法结束后通过ConfigurationClassBeanDefinitionReader
加载).
最后parse()
就是调用processDeferredImportSelectors()
对spring boot的自动配置进行加载了,和上面一样,最终调用processConfigurationClass()
解析配置类.但import
导入的自动配置的bean注册会在另外的地方进行(解析parse()
方法结束后通过ConfigurationClassBeanDefinitionReader
加载).
BeanDefinitionRegistryPostProcessor
运行完spring内置的bean定义注册后处理器后,spring还会循环运行第三方的实现BeanDefinitionRegistryPostProcessor
接口的处理器(如mybatis的MapperScannerConfigurer
),直到没有新的bean定义注册后处理器出现才会停止.