在 SpringBoot源码解读与原理分析(八)ApplicationContext 中,梳理了是ApplicationContext的几个重要实现类,其中AbstractApplicationContext显得尤为重要:
ApplicationContext的启动,其内部的核心动作的刷新容器,也就是AbstractApplicationContext中的refresh()方法。
AbstractApplicationContext.java
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// 1.初始化前的预处理
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 2.获取BeanFactory,加载所有bean的定义信息(未实例化)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 3.BeanFactory的预处理配置
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 4.准备BeanFactory完成后进行的后置处理
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 5.执行BeanFactory创建后的后置处理器
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 6.注册Bean的后置处理器
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 7.初始化MessageSource
initMessageSource();
// Initialize event multicaster for this context.
// 8.初始化事件广播器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 9.子类的多态onRefresh
onRefresh();
// Check for listener beans and register them.
// 10.注册监听器
registerListeners();
// 至此,BeanFactory创建完成
// Instantiate all remaining (non-lazy-init) singletons.
// 11.初始化所有剩下的单实例
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
// 12.完成容器的创建工作
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...
// 13.清理缓存
resetCommonCaches();
}
}
}
整个refresh方法分为13步,这篇文章只是梳理每一步都做了哪些事情,对于其中的细节设计放到之后的文章再展开。
/**
* Prepare this context for refreshing, setting its startup date and
* active flag as well as performing any initialization of property sources.
*/
protected void prepareRefresh() {
// Switch to active.
// 切换IOC容器启动状态
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());
}
}
// Initialize any placeholder property sources in the context environment.
// 在上下文环境中初始化任何占位符属性源
initPropertySources();
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
// 验证标记为required的所有属性都是可解析的
getEnvironment().validateRequiredProperties();
// Store pre-refresh ApplicationListeners...
// 存储预刷新的ApplicationListeners
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);
}
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
// 收集早期ApplicationEvents
this.earlyApplicationEvents = new LinkedHashSet<>();
}
这一步骤大多数的动作都是前置性准备,包括切换IOC容器启动状态、初始化属性配置、属性检验、早期事件容器准备等。
AbstractApplicationContext.java
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
这一步骤的refreshBeanFactory方法是一个抽象方法,由子类实现。不同的实现行为也不同。
(1)基于注解配置类的落地实现:GenericApplicationContext
GenericApplicationContext.java
@Override
protected final void refreshBeanFactory() throws IllegalStateException {
if (!this.refreshed.compareAndSet(false, true)) {
throw new IllegalStateException(
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
}
this.beanFactory.setSerializationId(getId());
}
GenericApplicationContext的refreshBeanFactory方法中有一个CSA判断动作,控制着GenericApplicationContext不能反复刷新。
(2)基于XML配置文件的落地实现:AbstractRefreshableApplicationContext
从类名可知,这是可刷新的ApplicationContext。该类的refreshBeanFactory方法会解析XML配置文件,封装BeanDefinition注册到BeanDefinitionRegistry中。
AbstractApplicationContext.java
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
// 注册类加载器、表达式解析器等
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
// 编程式注册ApplicationContextAwareProcessor
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 interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
// 绑定BeanFactory和ApplicationContext的依赖注入映射
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 (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.
// 注册Environment抽象
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());
}
}
这一步骤的内部处理内容比较多,主要包含三件事情:
AbstractApplicationContext.java
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {}
这一步骤的方法本身是一个模板方法,由子类具体实现。
(1)基于Web环境的实现:GenericWebApplicationContext
GenericWebApplicationContext.java
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
if (this.servletContext != null) {
// 编程式注册ServletContextAwareProcessor
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
}
// 注册新的Bean的作用域
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
// 注册ServletContext
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
}
基于Web环境的实现GenericWebApplicationContext的postProcessBeanFactory方法做了3件事情:
(2)基于嵌入式Web容器的实现:ServletWebServerApplicationContext
ServletWebServerApplicationContext.java
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
registerWebApplicationScopes();
}
这种方式是SpringBoot主要使用的,与基于Web环境的实现GenericWebApplicationContext相比,主要区别有:
PostProcessorRegistrationDelegate.java
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
// 执行所有的BeanDefinitionRegistryPostProcessor
Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry) {
// ...
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
// 执行所有的BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
//...
}
这一步骤会回调执行所有的BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor。在 SpringBoot源码解读与原理分析(十二)后置处理器 中详细梳理了这两个后置处理器的作用:
PostProcessorRegistrationDelegate.java
public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// 初始化所有的BeanPostProcessor
// ...
}
这一步骤会初始化所有的BeanPostProcessor。
在 SpringBoot源码解读与原理分析(十二)后置处理器 中详细梳理了BeanPostProcessor的作用:它可以干预bean对象的实例化、初始化逻辑,postProcessBeforeInitialization在bean对象的初始化逻辑之前执行,postProcessAfterInitialization在初始化逻辑之后执行。另外postProcessAfterInitialization还可以对FactoryBean创建出的真实对象进行后置处理。
当前步骤初始化BeanPostProcessor时,由于容器中还没有初始化任何业务相关的bean对象,所以后续初始化的所有bean对象都会经过BeanPostProcessor的干预。
AbstractApplicationContext.java
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// Make MessageSource aware of parent MessageSource.
// ...
if (logger.isTraceEnabled()) {
logger.trace("Using MessageSource [" + this.messageSource + "]");
}
} else {
// Use empty MessageSource to be able to accept getMessage calls.
// 未作配置时使用空的MessageSource
DelegatingMessageSource dms = new DelegatingMessageSource();
// ...
if (logger.isTraceEnabled()) {
logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
}
}
}
这一步骤会初始化默认的国际化组件,但默认的实现类DelegatingMessageSource在不作任何附加配置时不会处理任何国际化的工作,只有手动向IOC容器注册具体的国际化组件,应用上下文才具备国际化的能力。
AbstractApplicationContext.java
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
// 如果手动配置了ApplicationEventMulticaster,则使用配置的
this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
} else {
// 如果没有配置,则使用SimpleApplicationEventMulticaster
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled()) {
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " + "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
这一步骤会初始化ApplicationEventMulticaster,如果没有手动注册,则使用默认的简单实现SimpleApplicationEventMulticaster。
AbstractApplicationContext.java
protected void onRefresh() throws BeansException {
// For subclasses: do nothing by default.
}
这是一个模板方法,默认没有任何实现。
借助IDEA可以查找到实现了该方法的类:
ReactiveWebServerApplicationContext中的扩展用于初始化基于Reactive环境的Web容器,ServletWebServerApplicationContext中的扩展用于初始化基于Servlet环境的Web容器。
AbstractApplicationContext.java
protected void registerListeners() {
// Register statically specified listeners first.
// 注册静态指定的监听器
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
// 只绑定baenName而不直接取出监听器的原因:不让所有常规bean对象初始化
// 后置处理器才能有机会干预
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
这一步骤讲BeanDefinitionRegistry中注册的所有监听器(ApplicationListener)的beanName取出,绑定到事件广播器(ApplicationEventMulticaster)中。只绑定beanName而不直接取出监听器的原因是,考虑到ApplicationListener作为IOC容器中的Bean,应该和其他常规Bean放在一起统一创建和初始化,以让后置处理器有机会干预它们。
AbstractApplicationContext.java
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
// 初始化用于类型转换的解析器
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no BeanFactoryPostProcessor
// (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
// 初始化用于表达式解析的解析器
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
// 初始化所有非延迟加载的单实例bean对象
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
这一步骤主要完成2件事情,并且该步骤执行完毕后,BeanFactory的初始化工作结束:
这一步骤执行了一些比较零散的动作,详见注释。
AbstractApplicationContext.java
protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
// 清理上下文级别的资源缓存(例如扫描中的ASM元数据)
clearResourceCaches();
// Initialize lifecycle processor for this context.
// 初始化生命周期处理器
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
// 传播生命周期处理器,回调所有Lifecycle类型Bean的start方法
getLifecycleProcessor().onRefresh();
// Publish the final event.
// 广播ContextRefreshedEvent事件
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
// 激活状态下,参与LiveBeansView MBean
LiveBeansView.registerApplicationContext(this);
}
AbstractApplicationContext.java
protected void resetCommonCaches() {
ReflectionUtils.clearCache();
AnnotationUtils.clearCache();
ResolvableType.clearCache();
CachedIntrospectionResults.clearClassLoader(getClassLoader());
}
这一步骤清除一些无用的缓存,包括ReflectionUtils、AnnotationUtils、ResolvableType、CachedIntrospectionResults中的缓存。
总结:
纵观整个refresh方法,每个动作的职责都很清晰。在整个过程中,有对BeanFactory的处理,有对ApplicationContext的处理,有准备BeanPostProcessor的处理,有准备ApplicationListener的逻辑,最后初始化一些非延迟加载的单实例bean对象。refresh方法执行完毕后,也就宣告对ApplicationContext初始化完成。
第3章到此就梳理完毕了,本章的主题是SpringBoot的IOC容器。回顾一下本章的梳理的内容:
(七)BeanFactory
(八)ApplicationContext
(九)SpringBoot对IOC容器的拓展
(十)Environment
(十一)BeanDefinition
(十二)后置处理器
(十三)IOC容器的启动流程
更多内容请查阅分类专栏:SpringBoot源码解读与原理分析
第4章主要梳理SpringBoot的核心引导:SpringApplication。主要内容包括: