目录
使用的spring源码版本 5.2.15.RELEASE
AbstractApplicationContext 是高级容器的基本实现类,此处围绕 AbstractApplicationContext 的 refresh() 方法进行讲述。
高级容器的构造方法
以常用的高级容器 ClassPathXmlApplicationContext 为例
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
//设置父上下文
super(parent);
//设置配置文件位置
setConfigLocations(configLocations);
//加载或刷新配置,使配置文件生效
if (refresh) {
refresh();
}
}
核心是调用父类的 refresh() 方法
refresh() 刷新容器
方法定义
ConfigurableApplicationContext 接口定义的 refresh()
/**
* Load or refresh the persistent representation of the configuration, which might be from Java-based configuration,
* an XML file, a properties file, a relational database schema, or some other format.
*
* As this is a startup method, it should destroy already created singletons if it fails, to avoid dangling resources.
*
* In other words, after invocation of this method, either all or no singletons at all should be instantiated.
*/
void refresh() throws BeansException, IllegalStateException;
refresh() 用于加载或刷新持久化配置,这些配置可以来自多种格式的配置文件、基于java代码的配置。
refresh() 是容器的启动方法,会重建应用上下文(ApplicationContext ),如果方法执行失败,会销毁所有已创建好的单例,即要么执行成功所有单例都已实例化,要么执行失败所有单例都没有实例化。
方法实现
AbstractApplicationContext 类实现的 refresh()
//操作容器的同步锁,在对容器进行refresh、destroy操作时使用
private final Object startupShutdownMonitor = new Object();
@Override
public void refresh() throws BeansException, IllegalStateException {
//加锁,防止多线程同时对容器进行refresh、destroy操作
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// 准备上下文的刷新
prepareRefresh();
// 获取最新的内置低级容器
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 准备要使用的BeanFactory实例
prepareBeanFactory(beanFactory);
try {
//预留的扩展点
//protected修饰的空方法,留给子类重写,可在容器创建、标准配置后做一些额外处理,比如注册一些特殊的BeanPostProcessor
postProcessBeanFactory(beanFactory);
//调用BeanFactory所有的后置处理器,用于修改beanFactory中的bean定义
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
invokeBeanFactoryPostProcessors(beanFactory);
//注册Bean的后置处理器
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
//初始化 MessageSource
initMessageSource();
//初始化应用事件广播器
initApplicationEventMulticaster();
//protected修饰的空方法,作为扩展点预留给子类重写,用于初始化子类定义的一些特殊bean
onRefresh();
//注册应用监听器
registerListeners();
//初始化所有剩余单例(懒加载的除外)
finishBeanFactoryInitialization(beanFactory);
//完成刷新的最后操作
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
//销毁所有已创建单例
destroyBeans();
//将context的激活状态(active标识)重置为false
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
contextRefresh.end();
}
}
}
refresh()方法流程图
refresh() 过程解析
prepareRefresh() 准备上下文的刷新
// 当前context开始启动的系统时间,ms
private long startupDate;
// 当前context是否处于激活状态
private final AtomicBoolean active = new AtomicBoolean();
//当前context是否已经关闭
private final AtomicBoolean closed = new AtomicBoolean();
//存储应用监听器
private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
//预刷新阶段(pre-refresh)要使用的应用监听器
private Set<ApplicationListener<?>> earlyApplicationListeners;
//在多播创建好之前,用于存储待发布的应用事件
private Set<ApplicationEvent> earlyApplicationEvents;
protected void prepareRefresh() {
// 记录开始时间,设置 context (容器)状态
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 environment中的property sources的值原本是占位符,这一步会把占位符替换为对应的实例
initPropertySources();
// 校验所需属性是否合法
// 上一步是设置属性源,这一步是从属性源中解析得到属性值,并校验属性值是否合法
getEnvironment().validateRequiredProperties();
//初始化存储监听器的2个成员变量
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
//初始化存储早期应用事件的成员变量
this.earlyApplicationEvents = new LinkedHashSet<>();
}
主要是给刷新上下文做一些准备工作,包括
- 记录开始时间,设置 context|(容器)的状态、标识位
- 初始化属性源,校验所需属性是否合法
- 初始化存储应用监听器、存储早期应用事件的成员变量
obtainFreshBeanFactory() 获取最新的内置低级容器
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//刷新内置的低级容器
refreshBeanFactory();
//返回刷新后的低级容器
return getBeanFactory();
}
AbstractApplicationContext 只定义了 refreshBeanFactory() ,由子类提供实现,AbstractRefreshableApplicationContext 提供的实现如下
//内置的低级容器实例
@Nullable
private volatile DefaultListableBeanFactory beanFactory;
@Override
protected final void refreshBeanFactory() throws BeansException {
//如果内部已经有BeanFactory实例,则先销毁其中所有的bean、关闭beanFactory
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
//重新构建BeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
//设置beanFactory的序列化id
beanFactory.setSerializationId(getId());
//对beanFactory应用自定义配置,有2个配置项:是否允许BeanDefinition覆盖、是否允许循环依赖
customizeBeanFactory(beanFactory);
//加载、解析、注册所有的BeanDefinition
//这个类只提供了定义,由子类提供实现,包括xml、注解2种方式的实现
//bean的加载、注册、创建、管理这些容器基础功能都是由BeanFactory提供,自然是注册到beanFactory中
loadBeanDefinitions(beanFactory);
//赋给成员变量
this.beanFactory = beanFactory;
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
刷新低级容器这一步,完成了BeanDefinition的加载、解析、注册,十分重要,注意此时只是完成了BeanDefinition的注册,bean尚未初始化。
高级容器的基类是 ApplicationContext,ApplicationContext 继承自 BeanFactory,但实际上高级容器并未直接实现低级容器 BeanFactory 的功能,而是内置了一个低级容器实例来提供低级容器的功能,以成员变量的方式与低级容器进行交互,二者更接近组合,而非继承。
在 BeanFactory 的实现类中,DefaultListableBeanFactory 功能最为齐全,所以选择它作为低级容器的实现。DefaultListableBeanFactory 内置了一个map作为BeanDefinition注册表,存储所有bean的定义
//BeanDefinition的注册表,存储所有的BeanDefinition,key是beanName
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
prepareBeanFactory() 准备beanFactory
主要是对上一步创建的beanFactory实例进行标准化配置,配置 beanFactory的标准上下文特征
/**
* Configure the factory's standard context characteristics,
* such as the context's ClassLoader and post-processors.
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
if (!shouldIgnoreSpel) {
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
}
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}
}
finishBeanFactoryInitialization() 初始化所有剩余单例
实际是调用 DefaultListableBeanFactory 的 preInstantiateSingletons() 方法
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
//遍历所有的 BeanDefinition
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//如果bean不是抽象的、是单例、不是懒加载的,则进行实例化
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//不管是FactoryBean方式创建的单例,还是普通的单例,都是通过getBean()方法获取的实例
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
//获取实例
getBean(beanName);
}
}
}
else {
//获取实例
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
smartInitialize.end();
}
}
}
实质是通过 beanFactory的getBean() 创建所有剩余单例(懒加载的除外)的实例,FactoryBean方式的单例也会在这一步创建。
finishRefresh() 完成刷新的最后操作
protected void finishRefresh() {
//清除缓存的类加载器加载的资源
clearResourceCaches();
//创建生命周期管理器 LifecycleProcessor 实例,放到容器中
//如果beanFactory中有对应的bean定义,则执行 this.xxx = beanFactory.getBean(); getBean()创建实例放到容器中,并赋给高级容器对应的成员变量
//否则直接new一个实例,beanFactory.registerSingleton() 注册到容器中
initLifecycleProcessor();
//给容器中的所有单例添加生命周期管理
getLifecycleProcessor().onRefresh();
//广播上下文已刷新事件 ContextRefreshedEvent
publishEvent(new ContextRefreshedEvent(this));
//注册应用上下文
LiveBeansView.registerApplicationContext(this);
}
BeanFactoryPostProcessor、BeanPostProcessor的区别
都是后置处理器(PostProcessor),用于后续的加工处理,区别如下
- 加工对象不同:BeanFactoryPostProcessor用于对BeanFactory实例进行加工处理,BeanPostProcessor用于对Bean实例进行加工处理
- 作用时机不同:BeanFactoryPostProcessor作用于spring容器加载bean定义之后、bean实例化之前,BeanPostProcessor作用于bean的初始化阶段。
spring容器的扩展点
spring容器(AbstractApplicationContext)给子类预留了2个扩展点,都是protected修饰的空方法,留给子类重写
- postProcessBeanFactory() :可在容器创建、标准配置后做一些额外处理,比如注册一些特殊的BeanPostProcessor
- onRefresh():在创建bean实例阶段调用,用于初始化一些特殊的bean
spring容器的生命周期
高级容器集成了 Lifecycle 生命周期管理,本身也会作为bean放到容器中,会处于生命周期管理器的管理下。
spring容器的生命周期与上下文的4个事件息息相关。
1、应用启动时调用高级容器的 refresh() 方法创建、刷新容器
- 在 refresh() 的 finishRefresh() 阶段会创建生命周期管理器,调用容器的start()方法开启容器,添加生命周期管理,发布上下文开始事件 ContextStartedEvent
- 在refresh() 刷新上下文完成后,会发布上下文已刷新事件 ContextRefreshedEvent
2、容器刷新完成后一直处于运行(running)阶段,或者说上下文一直处于激活(active)阶段
3、终止jvm或调用高级容器的close()方法时,容器关闭
- 关闭容器时会调用容器的stop()方法,终止生命周期管理,发布上下文已停止事件 ContextStoppedEvent
- 容器关闭完成后会发布上下文已关闭事件 ContextClosedEvent