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的基本容器;
-
customizeBeanFactory(beanFactory);
根据AbstractRefreshableApplicationContext
类的属性为Beanfactory
设置属性值。
allowBeanDefinitionOverriding:属性是指是否允对一个名字相同但definition不同进行重新注册,默认是true。 allowCircularReferences属性是指是否允许Bean之间循环引用,默认是true
默认两个属性都为空,可扩展的,可以自己设置属性,方法就是继承ClassPathXmlApplicationContext
并复写customizeBeanFactory
方法为两个属性设置值即可。 -
loadBeanDefinitions(beanFactory);
将BeanDenifition
注册到bean
工厂
[图片上传失败...(image-e0509-1560845367203)]查看最后一个方法:
loadBeanDefinitions(beanDefinitionReader);
例如:applicationContext.xml
不是在calsspath
下了,只有Resource
,那怎么办,直接传递进来即可,继承ClassPathXmlApplicationContext
类重写getConfigResources
方法,返回Resource
即可。
3. prepareBeanFactory();
在ApplicationContext
刷新获取beanFactory
之后,开始准备context
使用的beanFactory
。这一步相对比较简单,就是配置beanFacotry
的特性
-
beanFactory.setBeanClassLoader(getClassLoader());
设置类加载器;设置BeanFactory
的BeanClassLoader
,如果存在,则直接使用之前的那个,否则,初始化一个新的ClassLoader
; 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注入当前对象
-
beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)
如果当前BeanFactory
包含loadTimeWeaver
Bean,说明存在类加载期织入AspectJ
,则把当前BeanFactory
交给类加载期BeanPostProcessor
实现类LoadTimeWeaverAwareProcessor
来处理,从而实现类加载期织入AspectJ
的目的。
- 注册当前容器环境
environment
组件Bean
[图片上传失败...(image-edc8e7-1560845367203)] - 注册系统配置
systemProperties
组件Bean
- 注册系统环境
systemEnvironment
组件Bean
总结:
(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(),以及发布