小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
前言:本文主要是讲 Spring 容器的启动过程主要是以题干的方式进行可能不回涉及过多的细节,希望大家阅读本文能对 Spring 容器初始化过程有一个简单的了解。 环境介绍:
- Spring 5.3.10
- Jdk 11
创建 Spring 容器
我们创建 Spring 容器可以通过一行代码进行创建
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(AppConfig.class);
在这个过程中核心就是调用 AnnotationConfigApplicationContext
的构造方法
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
// 刷新上下文
refresh();
}
Spring 容器创建过程 refresh 方法分析
Spring 容器创建过程主要就是调用 refresh()
方法。我们先一起看看 refresh()
方法具体做了哪些事。具体分为一下几个步骤:
prepareRefresh
预刷新方法,主要是用来初始化和读取上下文配置信息;obtainFreshBeanFactory()
创建 BeanFactory 对象,其实就是创建一个 Bean 工厂;prepareBeanFactory(beanFactory)
配置 Bean 工厂,比如设置 ClassLoader、BeanPostProcessor
等;postProcessBeanFactory
允许子类进行拓展;invokeBeanFactoryPostProcessors
实例化并调用所有已注册的 BeanFactoryPostProcessor 。调用 BeanFactoryPostProcessor 需要按照顺序调用,优先级是a. 实现_PriorityOrdered_
接口;b. 实现Order
接口; c. 默认。- registerBeanPostProcessors 注册 Bean 对象的
BeanPostProcessors
; initMessageSource
初始化 messageSource 其实就是为了支持国际化;initApplicationEventMulticaster
初始化事件发布器;onRefresh
模板方法,可以给子类实现,以完成特殊的处理registerListeners
注册事件监听器,Spring 中的事件机制,其实就是一个典型的观察者模式,这里其实就是注册观察者。finishBeanFactoryInitialization
完成初始化单实例的非懒加载的 Bean 对象, 这里非常关键,对于 Bean 的初始化,属性填充,Aop 等都可以跟着这个方法找到。finishRefresh
完成初始化,这里会发布一个ContextRefreshedEvent
容器初始化完成事件,以及做一些其他的处理。
对这个过程我们又一个大概的了解过后,我们再来看看 refresh()
方法的定义:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
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();
}
}
}