Spring教程之教程之refresh()执行逻辑浅析执行逻辑浅析
主要给大家介绍了关于Spring教程之refresh()执行逻辑的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友
们下面随着小编来一起学习学习吧
前言前言
对于AbstractApplicationContex#refresh()方法逻辑,可所谓是贯通spring框架核心逻辑,溪源在debug过程中,理解起来也是懵懵懂懂,自己也买了《Spring源码深度解析》书籍学习其思
想和实现逻辑,经过不断的整理学习总结,最终诞生这篇文章,方便后面自己忘记了查看和理解。
下面开始正式踏入refresh方法的整体概览浅析。
概览概览
refresh
该方法是 Spring Bean 加载的核心,它是 ClassPathXmlApplicationContext 的父类 AbstractApplicationContext 的一个方法 , 顾名思义,用于刷新整个Spring 上下文信息,定义了整个
Spring 上下文加载的流程。
先看下refresh()方法总体:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备预处理:记录容器的启动时间startupDate, 标记容器为激活,初始化上下文环境如文件路径信息,验证必填属性是否填写
this.prepareRefresh();
// **告诉子类去刷新bean工厂,此方法解析配置文件并将bean信息存储到beanDefinition中,注册到BeanFactory(但是未被初始化,仅将信息写到了beanDefination的map中)**重点方法,下面的操作都基于这个beanFactory进行的
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
// 设置beanFactory的基本属性:类加载器,添加多个beanPostProcesser
this.prepareBeanFactory(beanFactory);
try {
// 空实现:允许子类上下文中对beanFactory做后期处理
this.postProcessBeanFactory(beanFactory);
/**************************以上是BeanFactory的创建及预准备工作 ****************/
// 调用BeanFactoryPostProcessor各个实现类的方法
this.invokeBeanFactoryPostProcessors(beanFactory);
// 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
this.registerBeanPostProcessors(beanFactory);
//初始化ApplicationContext的MessageSource组件(资源文件),如国际化文件,消息解析,绑定等
this.initMessageSource();
//初始化ApplicationContext事件广播器
this.initApplicationEventMulticaster();
// 初始化子类特殊bean(钩子方法)
this.onRefresh();
// 获取所有的事件监听器,并将监听器注册到事件广播器
this.registerListeners();
//** 初始化所有singleton bean;**重点方法
this.finishBeanFactoryInitialization(beanFactory);
// 广播事件:ApplicationContext初始化完成
this.finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex);
}
// 销毁bean
this.destroyBeans();
// 重置 'active' 标志.
this.cancelRefresh(ex);
throw ex;
}
}
明细明细
本篇文章,不会仔细往下探讨源码实现逻辑,先总结refresh()方法具体逻辑:
1.prepareRefresh
准备预处理:记录spring容器的启动时间startupDate, 标记容器为激活,初始化上下文环境如文件路径信息,验证必填属性是否填写。
initPropertySources():初始化一些属性设置;子类自定义个性化的属性设置方法;
getEnvironment().validateRequiredProperties():检验属性的合法等;
earlyApplicationEvents= new LinkedHashSet():保存容器中的一些早期的事件;
//刷新前的预处理;
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// 初始化一些属性设置;子类自定义个性化的属性设置方法;
initPropertySources();
// 校验配置文件的属性,合法性
getEnvironment().validateRequiredProperties();
//保存容器中的一些事件
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}
2.obtainFreshBeanFactory
获取BeanFactory,解析配置文件,生成beanDefinition;
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory(); //创建了一个this.beanFactory = new DefaultListableBeanFactory();设置了序列化的ID
//返回刚才创建的DefaultListableBeanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
3.prepareBeanFactory
该方法主要负责对BeanFactory的预准备工作,配置beanFactory的基础属性,比如ClassLoader和一些PostProcessor等。
这个方法主要是给BeanFactory设置一些基本的属性,比如类加载器、表达式解析器、属性编辑器,注册几个单例、添加一些不用注入的接口、添加解析依赖项等。
设置BeanFactory的类加载器、支持表达式解析器…
添加部分BeanPostProcessor【ApplicationContextAwareProcessor】
设置忽略的自动装配的接口EnvironmentAware、EmbeddedValueResolverAware、xxx;