springboot在启动的时候,会调用run方法,创建环境设置spring容器,其中包含refresh方法,完成配置类解析,各种beanFactoryPostProcess和beanPostProcessor注册,web内置容器构造,国际化配置初始化等,refresh调用了父类AbstractApplicationContext的refresh方法如下。
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备,记录容器的启动时间startupDate, 标记容器为激活,初始化上下文环境如文件路径信息,验证必填属性是否填写
prepareRefresh();
// 这步比较重要(解析),告诉子类去刷新bean工厂,这步完成后配置文件就解析成一个个bean定义,注册到BeanFactory(但是未被初始化,仅将信息写到了beanDefination的map中)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 设置beanFactory类加载器,添加多个beanPostProcesser
prepareBeanFactory(beanFactory);
try {
// 允许子类上下文中对beanFactory做后期处理
postProcessBeanFactory(beanFactory);
// 调用BeanFactoryPostProcessor各个实现类的方法
invokeBeanFactoryPostProcessors(beanFactory);
// 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
registerBeanPostProcessors(beanFactory);
//初始化ApplicationContext的MessageSource
initMessageSource();
//初始化ApplicationContext事件广播器
initApplicationEventMulticaster();
// 初始化子类特殊bean(钩子方法)
onRefresh();
// 注册事件监听器
registerListeners();
// 初始化所有singleton bean 重点!!重点!!
finishBeanFactoryInitialization(beanFactory);
// 广播事件,ApplicationContext初始化完成
finishRefresh();
} catch (BeansException ex) {
....................
}

1. prepareRefresh()
在rehresh之前做的准备工作,一是设置spring启动事件,开启活跃状态;二是初始化属性源信息;三是验证必要属性。

1.1 initPropertySources()
在应用启动之前替换一些属性占位符,这个方法再Spring的对象中一般都没有实现,应该是用来方便我们后期扩展使用的方法。
1.2 validateRequiredProperties()
Environment类的方法验证必须的属性是否正确。
2. obtainFreshBeanFactory();
获取新的beanFactory,销毁原有beanFactory、为每个bean生成BeanDefinition等
obtainFreshBeanFactory方法从字面的意思看获取新的Bean工厂,实际上这是一个过程,一个加载Xml资源并解析,根据解析结果组装BeanDefinitions,然后初始化BeanFactory的过程。如下图跳入方法源码中

2.1 refreshBeanFactory()
refreshBeanFactory是具体的刷新BeanFactory,负责这个工作做在类AbstractRefreshableApplicationContext中,顾名思义这是专门用来刷新的。

详细说明:
- 首先判断,是否存在
BeanFactory,如果存在容器beanFactory,则先销毁所有的bean,然后关闭beanFactory; -
DefaultListableBeanFactory beanFactory = createBeanFactory();创建初始容器beanFactory,此处创建的是DefaultListableBaenFactory,是最重要的beanFactory,即初始化容器;spring注册&加载bean的基本容器;
image -
customizeBeanFactory(beanFactory);根据AbstractRefreshableApplicationContext类的属性为Beanfactory设置属性值。
image
allowBeanDefinitionOverriding:属性是指是否允对一个名字相同但definition不同进行重新注册,默认是true。 allowCircularReferences属性是指是否允许Bean之间循环引用,默认是true
默认两个属性都为空,可扩展的,可以自己设置属性,方法就是继承ClassPathXmlApplicationContext并复写customizeBeanFactory方法为两个属性设置值即可。 -
loadBeanDefinitions(beanFactory);将BeanDenifition注册到bean工厂
[图片上传失败...(image-e0509-1560845367203)]查看最后一个方法:
loadBeanDefinitions(beanDefinitionReader);
image
例如:applicationContext.xml不是在calsspath下了,只有Resource,那怎么办,直接传递进来即可,继承ClassPathXmlApplicationContext类重写getConfigResources方法,返回Resource即可。
3. prepareBeanFactory();
在ApplicationContext刷新获取beanFactory之后,开始准备context使用的beanFactory。这一步相对比较简单,就是配置beanFacotry的特性
-
beanFactory.setBeanClassLoader(getClassLoader());设置类加载器;设置BeanFactory的BeanClassLoader,如果存在,则直接使用之前的那个,否则,初始化一个新的ClassLoader;image beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));设置BeanExpressionResolver表达式解析器,主要用来解析EL表达式;Bean初始化完成后填充属性时会用到beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));设置属性注册解析器PropertyEditor;这个主要是对某些注入的Bean的一些属性的支持;beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor (this));此处添加了一个BeanPostProcessor实现:ApplicationContextAwareProcessor,它是用来处理并回调实现了各种Aware接口的Bean,比如获取ApplicationContext的ApplicationContextAware接口。添加BeanPostProcessor(Bean后置处理器ApplicationContextAwareProcessor),当bean被这个工厂创建的时候会用到PostProcessor, 在beanfactory中存储了beanPostProcessors的列表,在生效的时候,列表中的PostProcessor都会执行。 在bean初始化之前,调用ApplicationContextAwareProcessor的postProcessBeforeInitialization处理所有的Aware接口,进行如下操作:
// 如果bean实现了EmbeddedValueResolverAware接口,调用bean.setEmbeddedValueResolver
// 如果bean实现了ResourceLoaderAware接口,调用bean.setResourceLoader
// 如果bean实现了ApplicationEventPublisherAware接口,调用bean.setApplicationEventPublisher
// 如果bean实现了MessageSourceAware接口,调用bean.setMessageSource
// 如果bean实现了ApplicationContextAware接口,调用bean.setApplicationContext
-
beanFactory.ignoreDependencyInterface()指定的接口不会被自动注入进去。 -
beanFactory.registerResolvableDependency()设置几个自动装配规则,例如BeanFactory则注入beanFactory ResourceLoader,ApplicationEventPublisher,ApplicationContext注入当前对象
image -
beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)如果当前BeanFactory包含loadTimeWeaverBean,说明存在类加载期织入AspectJ,则把当前BeanFactory交给类加载期BeanPostProcessor实现类LoadTimeWeaverAwareProcessor来处理,从而实现类加载期织入AspectJ的目的。
image - 注册当前容器环境
environment组件Bean
[图片上传失败...(image-edc8e7-1560845367203)] - 注册系统配置
systemProperties组件Bean
image - 注册系统环境
systemEnvironment组件Bean
image
总结:
(1)设置类加载器 (2)设置EL表达式解析器(bean创建完成填充属性时使用)和属性注册解析器 (3)利用beanPostProcessor的特性给各种Aware接口的实现类注入ApplicationContext中对应的属性; (4)设置各种Aware接口的实现类为忽略自动装配 (5)设置自动装配类(BeanFactory,ResourceLoader,ApplicationEventPublisher,ApplicationContext) (6)如果BeanFactory中存在loadTimeWeaver的bean,那么需要添加动态织入功能 (7).注册各种可用组件(environment,systemProperties,systemEnvironment)
4.postProcessBeanFactory()
bean工厂的bean属性处理容器,说通俗一些就是可以管理我们的bean工厂内所有的beandefinition(未实例化)数据;
postProcessBeanFactory后处理beanFactory。时机是在所有的beanDenifition加载完成之后,bean实例化之前执行。
比如,在beanfactory加载完成所有的bean后,想修改其中某个bean的定义,或者对beanFactory做一些其他的配置,就可以用此方法。在系列文章中,可以实现ClassPathXmlApplicationContext类并重写postProcessBeanFactory即可。
默认情况下此方法是空的。需要子类去实现
注意:
BeanFactoryPostProcessor的主要作用是让你能接触到bean definitions,对bean definitions进行一定hack,但是也仅此而已了。绝对不允许在BeanFactoryPostProcessor中触发到bean的实例化!
举例:
@Component
public class PrematureBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
Map<String, BBean> map = beanFactory.getBeansOfType(BBean.class);
for (BBean bBean : map.values()) {
assert bBean.getABean() == null;
}
}
}
@Component("bBean")
public class BBean {
@Autowired
private ABean aBean;
public ABean getABean() {
return aBean;
}
}
@Component
public class ABean {
private String name = "a";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
在运行后,BBean中被期待注入的ABean最终为null。这是为啥呢?postProcessBeanFactory(beanFactory); 首先invoke了容器中的BeanFactoryPostProcessor实现类,其中当然就包括PrematureBeanFactoryPostProcessor,此时通过beanFactory.getBeansOfType触发了bean提前实例化。按理说,bean提前实例化也应该没问题的,aBean也应该是能够被注入的呀!那为啥最终不是这个结果呢?
从源码可知:
@AutoWired起作用依赖AutowiredAnnotationBeanPostProcessor;
@Resource依赖CommonAnnotationBeanPostProcessor,这俩都是BeanPostProcessor的实现。
那BeanPostProcessors在何处被spring invoke呢?
参见refresh()方法registerBeanPostProcessors(beanFactory);
在postProcessBeanFactory(beanFactory);后面被调用;
也就是说BBean被触发提前初始化的时候,AutowiredAnnotationBeanPostProcessor还没有被注册自然也不会被执行到,自然ABean=null。
5.invokeBeanFactoryPostProcessors(beanFactory);
实例化Factory之前预处理部分
invokeBeanFactoryPostProcessors 方法主要用于处理 BeanFactoryPostProcessor 接口。BeanFactoryPostProcessor 接口是 Spring 初始化 Bean 时对外暴露的扩展点,Spring IoC 容器允许 BeanFactoryPostProcessor 在容器实例化任何 Bean 之前读取Bean 的定义,并可以修改它。
可以理解为,初始化我们自定义的BeanFactoryPostProcessor;
postProcessBeanFactory用于在标准的初始化完成后修改容器上下文中的beanFactory。所有bean定义将被加载,但是它们将暂时不被实例化,这允许覆盖,甚至添加一些属性到延迟初始化的bean上。也就是说,允许我们开发者自定义的去修改BeanFactory中的内容,这也是符合“spring”的开闭原则。invokeBeanFactoryPostProcessors,就是调用postProcessBeanFactory。

5.1. getBeanFactoryPostProcessors()
获取的手动注册的BeanFactoryPostProcessor;
是通过beanFactory.addBeanPostProcessor()方法设置的BeanFactoryPostProcessor。默认空的,因为没有通过addBeanFactoryPostProcessor方法添加BeanFactoryPostProcessor

5.2 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()
未完待续...
6. registerBeanPostProcessors(beanFactory);
注册BeanPostProcessor
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);


注册BeanPostProcessor和invokeBeanFactoryPostProcessors很像,并且没什么复杂逻辑。就是将已经注册到beanFacory的Bean筛选出BeanPostProcessor然后添加到ApplicationContext的beanPostProcessor集合中。
主要逻辑:
:首先在容器中注册一个
BeanPostProcessorChecker,这个只是用来对在bean不适合所有的BeanPostProcessor调用的情况下,打印一些日志信息。:先注册实现了
PriorityOrdered接口的BeanPostProcessor,再注册实现了Ordered接口的的BeanPostProcessor,然后注册什么接口都没实现的BeanPostProcessor,最后注册实现了MergedBeanDefinitionPostProcessor接口的BeanPostProcessor。:注册
ApplicationListenerDetector。用来检测bean是否是ApplicationListener,如果是判断是否是单例,如果不是单例,那么删除singtonNames中对应的key。
7. initMessageSource();初始化消息源
为本context初始化消息源;
判断beanFactory中是否有名字为messageSource的bean,如果有,从beanFactory中获取并且判断获取的是不是HierarchicalMessageSource类型的,如果是设置其父级消息源;如果没有,新建DelegatingMessageSource类作为messageSource的Bean。

8. initApplicationEventMulticaster();初始化应用事件广播器
初始化ApplicationEventMulticaster,
首先判断beanFactory容器中是否存在这个广播器:applicationEventMulticaster;
如果存在,则用beanFactory中的bean;如果不存在则使用新建SimpleApplicationEventMulticaster

9. onRefresh();
10. registerListeners();注册监听器
在发布事件的时候会从这里注册的监听器中去获取;

11.finishBeanFactoryInitialization(beanFactory);
完成此上下文的 bean 工厂的初始化,初始化所有剩余的单例 bean。实例化所有的非懒加载单例。是ApplicationContext刷新的时候,最重要的方法了,因为所有的bean,如果不是lazy-init的都会在这一步进行实例化,并且做一些处理。

12.finishRefresh();
完成对context的刷新
13.总结
1.prepareRefresh();对刷新进行准备,包括设置开始时间,设置激活状态,初始化Context中的占位符,子类根据其需求执行具体准备工作,而后再由父类验证必要参数
2.obtianFreshBeanFactory();,刷新并获取内部的BeanFactory对象
3.prepareBeanFactory(beanFactory);,对BeanFactory进行准备工作,包括设置类加载器和后置处理器,配置不能自动装配的类型,注册默认的环境Bean
4.postProcessBeanFactory(beanFactory);为Context的子类提供后置处理BeanFactory的扩展能力,如想在bean定义加载完成后,开始初始化上下文之前进行逻辑操作,可重写这个方法
5.invokeBeanFactoryPostProcessors(beanFactory);,执行Context中注册的BeanFactory后置处理器,有两张处理器,一种是可以注册Bean的后置处理器,一种的针对BeanFactory的后置处理器,执行顺序是先按优先级执行注册Bean的后置处理器,而后再按优先级执行针对BeanFactory的后置处理器
SpringBoot中会进行注解Bean的解析,由ConfigurationClassPostProcessor触发,由ClassPathDefinitionScanner解析,并注册到BeanFactory
6.registerBeanFactoryProcessor(beanFactory();,按优先级顺序在BeanFactory中注册Bean的后置处理器,Bean处理器可在Bean的初始化前后处理
7.initMessageSource();初始化消息源,消息源用于支持消息的国际化
8.initApplicationEventMuticaster();初始化应用事件广播器,用于向ApplicationListener通知各种应用产生的事件,标准的观察者模型
9.onRefresh();,用于子类的扩展步骤,用于特定的Context子类初始化其他的Bean
10.registerListeners();,把实现了ApplicationListener的类注册到广播器,并对广播其中早期没有广播的事件进行通知
11.finishBeanFactoryInitialization(beanFactory);,冻结所有Bean描述信息的修改,实例化非延迟加载的单例Bean
12.finishRefresh();,完成上下文的刷新工作,调用LifecycleProcessor.onRefresh(),以及发布







