1、Refresh方法简介
refresh
是Spring的核心流程,主要包含13个方法。这13个方法中主要又包含3个方法。
如图:
其中标记星号的代表主要的方法。从方法中后面的分支数据也可以看出,主要的方法中存在大量的逻辑处理,后面我们会慢慢分解开来梳理。
本章内容主要梳理前四个方法。
2、prepareRefresh
初始化上下文的环境
2.1 初始化标识
// Switch to active.
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);if (logger.isDebugEnabled()) {if (logger.isTraceEnabled()) {logger.trace("Refreshing " + this);}else {logger.debug("Refreshing " + getDisplayName());}
}
将当前Context环境标记成活跃状态,关闭状态置为false。其中
this
就是AnnotationConfigApplicationContext
。如图:
2.2 校验所有的属性并标记
// Initialize any placeholder property sources in the context environment.
initPropertySources();// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
initPropertySources
初始化上下文环境中的placeholder property sources
,主要是被子类实现用,默认空实现。这是一个钩子方法。
getEnvironment()
获取当前的上下文所需要的环境ConfigurableEnvironment
。默认会创建一个标准的环境。此环境可以获取到环境的变量和属性。
validateRequiredProperties()
获取所有的必须的属性,将其保存到MissingRequiredPropertiesException
对象中,如果环境运行,没有检测注册的必要属性就会抛出异常。
2.3 初始化监听器和事件
初始化监听器和事件。为后面发布事件做好准备。
3、obtainFreshBeanFactory()
获取一个内部的BeanFactory
3.1 刷新当前工厂
当前的工厂就是
DefaultListableBeanFactory
,GenericApplicationContext
的空参构造函数就会创建工厂。然后设置工厂的唯一标识
SerializationId
3.2 返回当前工厂
工厂返回的是一个接口
ConfigurableListableBeanFactory
,实现还是3.1
中的DefaultListableBeanFactory
4、prepareBeanFactory()
配置工厂标准环境的一些特性。
该方法大致40行代码左右,主要可以分为5部分:
忽略指定接口
注册解析依赖
添加
BeanPostProcessor(BPP)
注册环境默认的单例
其他特性
此分类会打乱该方法部分代码的顺序,部分代码执行会有先后的顺序要求。下面分析将按照分类梳理。
4.1 忽略指定接口
beanFactory.ignoreDependencyInterface(xxxx.class)
忽略的接口有:
-
EnvironmentAware.class
-
EmbeddedValueResolverAware.class
-
ResourceLoaderAware.class
-
ApplicationEventPublisherAware.class
-
MessageSourceAware.class
-
ApplicationContextAware.clas
-
ApplicationStartupAware.class
忽略指定的xxxxAware接口。因为xxxxAware接口是对外提供扩展,将xxxx本身暴露出去。所以BeanFactory处理的时候无需关心这些接口。只要关注实际的xxx接口本身就好了。
4.2 注册解析依赖
BeanFactory.class、ResourceLoader.class、 ApplicationEventPublisher.class、 ApplicationContext.class的处理军依赖当前的Bean工厂,所以建立对应关系。本质上就是维护一个一一对应的map集合。方便使用时直接获取。
4.3 添加BPP
BeanPostProcessor
是Bean初始化的后置处理器。可以再Bean初始化前后增强。
-
new ApplicationContextAwareProcessor(this)
上下文Aware处理器Bean初始化之前,处理实现Aware接口的类,为其设置环境和解析器
-
new ApplicationListenerDetector(this)
监听器的探测器该类实现了
DestructionAwareBeanPostProcessor
MergedBeanDefinitionPostProcessor
接口。分别在Bean定义后合并、Bean实例化之后、Bean销毁之前调用。如果当前Bean是
ApplicationListener
就会执行相应的逻辑。 -
new LoadTimeWeaverAwareProcessor(beanFactory)
编译时的代码织入在Bean初始化之前为Bean设置
LoadTimeWeaver
4.4 注册默认的单例
注册的单例:
-
environment 标准的配置环境
-
systemProperties 系统属性
-
systemEnvironment 系统的环境
-
applicationStartup 启动的Bean
4.5 其他的特性
为BeanFactory设置其他特性
beanFactory.setBeanClassLoader(getClassLoader());
设置类加载器,用来加载一些配置文件等信息
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()))
设置Bean的EL表达式的解析器
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
设置属性编辑注册器。
处理字符串和日期的对应关系时,我们可以注册String和Date的对应关系等。
5、postProcessBeanFactory(beanFactory)
给子类预留的钩子函数,默认空实现。springboot启动的时候就会用到(增加web容器的处理器)。