ApplicationContext的初始化过程
ClassPathXmlApplicationContext
ClassPathXmlApplication
会接收一个applicationContext.xml
(名称自定义)在类路径上描述spring bean的xml文件的构造方法。
- 初始化资源管理器
PathMatchingResourcePatternResolver
; - 解析xml路径上的占位符
${...}
; 调用
refresh()
方法,该方法是高级容器的启动主要方法。初始化容器上下文环境,主要内容为:
- 在上下环境中添加属性值用于替换占位符
${...}
; - 检测指定的环境变量是否已经配置。
- 在上下环境中添加属性值用于替换占位符
初始化低级容器
BeanFactory
:- 创建容器
DefaultListableBeanFactory
; 定制容器,为容器设置参数:
- 是否允许
BeanDefinition
被覆盖; - 是否允许循环依赖引用。
- 是否允许
- 将xml文件的解析交给
XmlBeanDefinitionReader
; 解析并注册,
XmlBeanFactory
的主要执行流程:- 从classpath路径加载xml的
Resource
; - 检验并解析
Resource
资源得到Document
; - 根据
Document
解析xml的各种属性标签; - 将解析到的信息封装到
BeanDefinition
中; - 注入到Spring容器
beanDefinitionMap
中。
- 从classpath路径加载xml的
- 创建容器
为BeanFacotry做一些初步的功能扩展:
- 添加对
SPEL
表达式语言的支持; - 注册属性编辑器;
- 添加执行器感知接口的后处理器;
- 添加
ApplicationContext
额外需要忽略的感知接口; - 为指定接口注册对应的实现类
- 添加对
BeanFactoryPostProcessor
接口方法的执行;- 处理参数传进来的
beanFactoryPostProcessor
; - 从
beanFactory
获取所有的BeanDefiitionRegistryPostProcessor
(PriorityOrdered
接口和Ordered
接口进行排序); - 从
beanFactory
中获取所有BeanFactoryPostProcessor
(PriorityOrdered
接口和Ordered
接口进行排序)。
- 处理参数传进来的
- 注册
BeanPostProcessor
:从beanFactory
中获取所有BeanPostProcessor
(PriorityOrdered
接口和Ordered
接口进行排序)注册到Spring
容器中; - 初始化消息源
MessageSource
; - 初始化事件广播器
ApplicationEventMulticaster
; - 注册监听器
ApplicationListener
; - 初始化非延迟加载的单例;
- 开启
Spring
的生命周期。
AnnotationConfigApplicationContext
AnnotationConfigApplicationContext
会接收一个扫描的包路径(名称自定义)的构造方法。
- 委托
ClassPathBeanDefinitionScanner
,将扫描的包路径转换为文件路径格式,例如:classpath*:com/test/**/*.class
,扫描出路径下的所有类并转换为资源Resource
数组; - 通过注解过滤器,过滤出标注了
@Component
的类并封装为注解类型的AnnotatedBeanDefinition
接口的实现类AnnotatedGenericBeanDefinition
; - 筛选出符合实例化bean条件的
BeanDefinition
,放入Set<BeanDefinition> candidates
; 循环处理每个
BeanDefinition
:- 解析
@Scope
注解的信息,并设置到BeanDefinition
中; - 设置
BeanDefinition
默认的一些属性值; - 解析其它注解信息:
@Lazy
、@Primary
、@DependsOn
、@Role
、@Description
;
- 解析
- 将
BeanDefinition
封装成BeanDefinitionHolder
,注入到Spring容器beanDefinitionMap
中; 调用
refresh()
方法,该方法是高级容器的启动主要方法。- 初始化容器上下文环境;
- 初始化低级容器
ConfigurableListableBeanFactory
; 为BeanFacotry做一些初步的功能扩展:
- 添加对
SPEL
表达式语言的支持; - 注册属性编辑器;
- 添加执行器感知接口的后处理器;
- 添加
ApplicationContext
额外需要忽略的感知接口; - 为指定接口注册对应的实现类
- 添加对
BeanFactoryPostProcessor
接口方法的执行(使用ConfigurationClassPostProcessor
后置处理器处理@Configuration
和@Bean
注解,流程在下一节);- 处理参数传进来的
beanFactoryPostProcessor
; - 从
beanFactory
获取所有的BeanDefiitionRegistryPostProcessor
(PriorityOrdered
接口和Ordered
接口进行排序); - 从
beanFactory
中获取所有BeanFactoryPostProcessor
(PriorityOrdered
接口和Ordered
接口进行排序)。
- 处理参数传进来的
- 注册
BeanPostProcessor
:从beanFactory
中获取所有BeanPostProcessor
(PriorityOrdered
接口和Ordered
接口进行排序)注册到Spring
容器中; - 初始化消息源
MessageSource
; - 初始化事件广播器
ApplicationEventMulticaster
; - 注册监听器
ApplicationListener
; - 初始化非延迟加载的单例;
- 开启
Spring
的生命周期。
ConfigurationClassPostProcessor
ConfigurationClassPostProcessor
实现了接口BeanDefinitionRegistryPostProcessor
,而BeanDefinitionRegistryPostProcessor
接口继承自BeanFactoryPostProcessor
,所以有两个关键的方法:BeanFactoryPostProcessor
接口的postProcessBeanFactory
方法和BeanDefinitionRegistryPostProcessor
接口的postProcessBeanDefinitionRegistry
方法。
postProcessBeanDefinitionRegistry方法
- 获取Spring容器中注册的所有
BeanDefinition
进行遍历; - 如果
BeanDefinition
配置了工厂方法,该BeanDefinition
不做处理,实现了工厂方法意味着在工厂方法中定义了实例化对象逻辑,不符合成为注解配置类BeanDefinition
的条件; - 获取
BeanDefinition
上的注解元数据metadata
,将存在注解@Configuration
且属性proxyBeanMethods
的值为true
的BeanDefinition
添加到集合configCandidates
中; - 对集合
configCandidates
根据注解@Order
进行排序; - 初始化注解配置类的解析器
ConfigurationClassParser
; - 解析注解配置类中的其它注解,例如:
@PropertySources
、@ComponentScans
、ImportResource
等; - 将解析后的集合对象
Set<ConfigurationClass>
; - 遍历集合
Set<ConfigurationClass>
,对ConfigurationClass
中每个添加了@Bean
的方法创建一个BeanDefition
,在填充一些默认属性后再注册到Spring容器中; - 同时对这些
@Bean
对应的BeanDefinition
进行重复检查(重复执行步骤3),以处理嵌套注解配置。
BeanFactoryPostProcessor方法
- 获取Spring容器中注册的所有
BeanDefinition
进行遍历; - 找到存在属性
CONFIGURATION_CLASS_ATTRIBUTE
且为AbstractBeanDefinition
实例的BeanDefinition
; - 初始化增强器
ConfigurationClassEnhancer
; - 遍历步骤2找到的
BeanDefinition
,获取BeanDefinition
的类名,使用增强器ConfigurationClassEnhancer
对configClass
进行增强,得到增强后的enchancedClass
; - 对
enchancedClass
设置回调接口BeanFactoryAwareMethodInterceptor
,为字段$$beanFactory
注入当前Spring容器对象; - 对
enchancedClass
设置回调接口BeanMethodInterceptor
,获取@Bean
对应的bean的名称beanName: 使用
&+beanName
获取FactoryBean
:未获取到
FactoryBean
:- 如果当前方法刚好是
@Bean
指定的工厂方法,通过@Bean
对应的bean的cglib动态代理来执行; - 如果当前方法不是
@Bean
指定的工厂方法,从Spring容器获取bean的实例来执行(也就是@Bean
方法中自定义创建的bean实例);
- 如果当前方法刚好是
获取到
FactoryBean
:- 类型或
getObject
方法存在final关键字修饰,如果@Bean
标注的方法返回值是接口类型的,就会通过jdk动态代理方式来生成FactoryBean
的动态代理,否则,就会直接返回FactoryBean
; - 如果
FactoryBean
的类或方法getObject
都没有被关键字final
修饰,此时会对FactoryBean
使用cglib动态代理的方式未FactoryBean
生成一个动态代理; - 不管是jdk动态代理还是cglib动态代理,如果当前bean实例调用的方法名称是
getObject
,此时会根据bean的名称,从Spring容器中获取bean的实例。
- 类型或