1、Refresh方法简介
refresh是Spring的核心流程,主要包含13个方法。这13个方法中主要又包含3个方法。
如图:

其中标记星号的代表主要的方法。从方法中后面的分支数据也可以看出,主要的方法中存在大量的逻辑处理,后面我们会慢慢分解开来梳理。
本章内容主要梳理前四个方法。
2、prepareRefresh 初始化上下文的环境

2.1 初始化标识
java
// 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 校验所有的属性并标记
java
// 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 忽略指定接口
java
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)监听器的探测器该类实现了
DestructionAwareBeanPostProcessorMergedBeanDefinitionPostProcessor接口。分别在Bean定义后合并、Bean实例化之后、Bean销毁之前调用。如果当前Bean是
ApplicationListener就会执行相应的逻辑。 -
new LoadTimeWeaverAwareProcessor(beanFactory)编译时的代码织入在Bean初始化之前为Bean设置
LoadTimeWeaver
4.4 注册默认的单例

注册的单例:
-
environment 标准的配置环境
-
systemProperties 系统属性
-
systemEnvironment 系统的环境
-
applicationStartup 启动的Bean
4.5 其他的特性
为BeanFactory设置其他特性
java
beanFactory.setBeanClassLoader(getClassLoader());
设置类加载器,用来加载一些配置文件等信息
java
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()))
设置Bean的EL表达式的解析器
java
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
设置属性编辑注册器。
处理字符串和日期的对应关系时,我们可以注册String和Date的对应关系等。
5、postProcessBeanFactory(beanFactory)
给子类预留的钩子函数,默认空实现。springboot启动的时候就会用到(增加web容器的处理器)。

