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的实例。 
- 类型或