前言
通过对Spring启动流程源码的分析,能够使我们对spring掌握的更透彻。本篇博文通过5.2.19版本的源码以 new ClassPathXmlApplicationContext("classpath:/spring/applicationContext.xml") 为入口,分析spring的启动过程,主要分析内容会在代码的注释中体现。
代码入口
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
ac.getBean("");
在调试过程中经常使用这段代码获取springbean,所以就通过ClassPathXmlApplicationContext类入手,分析spring启动加载的流程。
源码分析
ClassPathXmlApplicationContext类的继承和实现关系图
这里需要先熟悉它的继承关系 如 AbstractApplicationContext、AbstractRefreshableConfigApplicationContext,后续可以更好的理解源码中的调用链。
ClassPathXmlApplicationContext构造方式——程序入口
classPathXmlApplicationContext中有很多构造方法,我这里用到是传递配置文件路径构造方法。
classPathXmlApplicationContext的父类AbstractRefreshableConfigApplicationContext有configLocations参数 是一个String[]数组,用于存放配置文件的路径。所以拿到一个配置文件后new String[]传递。
/**
* 创建一个新的 ClassPathXmlApplicationContext,从给定的 XML 文件加载定义并自动刷新上下文。
*/
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
/**
* 通过给定的配置文件组,创建上下文对象
* 根据refresh参数判定,是否刷新所有的bean
*/
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
// 调用父类构造
super(parent);
// 调用父类的父类AbstractRefreshableConfigApplicationContext.setConfigLocations
// 1 - 将配置文件路径存储成员变量中 String[] configLocations
// 2 - 调用org.springframework.core.env.PropertyResolver#resolveRequiredPlaceholders 解析配置文件路径中的 ${} 占位符,将它们替换为相应的值。
setConfigLocations(configLocations);
if (refresh) {
// 这里父类org.springframework.context.support.AbstractApplicationContext的方法
// 用于刷新整个spring上下文信息,是spring的核心内容
refresh();
}
}
AbstractApplicationContext
它是org.springframework.context.ApplicationContext 接口的抽象实现类,简单地实现通用的上下文功能,具体个性化的功能还需要子类实现抽象方法。
AbstractApplicationContext.refresh()方法分析
refresh方法几乎包含了ApplicationContext的所有功能,其方法内部的执行逻辑可概括为以下几点:
- 初始化前的准备工作,如对系统变量环境变量的解析
- 初始化BeanFactory,并进行XML读取
- 对BeanFactory功能的功能进行填充,如@Autowired就是在这一步增加的支持。
- 子类覆盖方法做额外处理,方便后续对框架的扩展
- 激活各种BeanFactory处理器
- 注册拦截bean创建的bean处理器。
- 为上下文初始化消息源。
- 初始化消息广播器
- 留给子类初始化其他的bean
- 查找所有ListenerBean,注册到消息广播器中。
- 初始化剩下的单例实例(非惰性)
- 完成刷新
/**
* 加锁避免多线程刷新上下文
*
* refresh()和 destroy()同用一个对象锁锁,避免refresh()和 destroy()方法冲突。
* */
private final Object startupShutdownMonitor = new Object();
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备此上下文以进行刷新。
prepareRefresh();
// 通知子类刷新内部bean factory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 准备 bean 工厂以在此上下文中使用
prepareBeanFactory(beanFactory);
try {
// 允许在上下文子类中对 bean 工厂进行后处理
postProcessBeanFactory(beanFactory);
// 调用在上下文中注册为 bean 的工厂处理器
invokeBeanFactoryPostProcessors(beanFactory);
// 注册拦截 bean 创建的 bean 处理器
registerBeanPostProcessors(beanFactory);
// 为此上下文初始化消息源。
initMessageSource();
// 为此上下文初始化事件多播器
initApplicationEventMulticaster();
// 初始化特定上下文子类中的其他特殊bean
onRefresh();
// 检查并注册监听器
registerListeners();
// 实例化剩余的单例对象
finishBeanFactoryInitialization(beanFactory);
// 发布相应的事件
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 销毁已经创建的单例以避免悬空资源
destroyBeans();
// 重置 active
cancelRefresh(ex);
throw ex;
}
finally {
// 刷新缓存
resetCommonCaches();
}
}
}
refresh方法将复杂的代码流程,拆分为若干个子方法,流程看起来非常清晰,方便阅读,下面再细细分析每一个子方法。
环境准备
AbstractApplicationContext.prepareRefresh()
/**
* 设置上下文对象启动时间、活动标识以及执行属性的初始化
* 准备此上下文以进行刷新、设置其启动日期和活动标志以及执行任何属性源的初始化。
*/
protected void prepareRefresh() {
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());
}
}
initPropertySources();
getEnvironment().validateRequiredProperties();
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
this.earlyApplicationEvents = new LinkedHashSet<>();
}
初始化BeanFactory
AbstractApplicationContext.obtainFreshBeanFactory()
/**
* 通知子类,刷新beanFactory
*
* @see #refreshBeanFactory()
* @see #getBeanFactory()
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 这两个都是抽象方法,供实现类实现具体刷新策略
refreshBeanFactory();
return getBeanFactory();
}
从最上面的类图中得知,ClassPathXmlApplicationContext调用的是AbstractRefreshhableApplicationContext的实现。
/**
* 此实现执行此上下文的底层 bean 工厂的实际刷新,关闭以前的 bean 工厂(如果有)
* 并为上下文生命周期的下一阶段初始化一个新的 bean 工厂。
*/
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
// 如果有beanFactory, 销毁factory中的bean 清空beanFactory
destroyBeans();
closeBeanFactory();
}
try {
// 创建一个新的beanFactory
// 指定DefaultListableBeanFactory,这是构造bean的核心类,非常重要
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 指定当前上下文对象的ID为beanFactory的序列化ID , 允许将此 BeanFactory 从此 id 反序列化回 BeanFactory 对象。
beanFactory.setSerializationId(getId());
// 自定义此上下文使用的内部 bean 工厂
customizeBeanFactory(beanFactory);
// 将 BeanDefinition 委托给beanFactory
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
// 返回 refreshBeanFactory() 方法创建的 beanFactory
DefaultListableBeanFactory beanFactory = this.beanFactory;
if (beanFactory == null) {
throw new IllegalStateException("BeanFactory not initialized or already closed - " +
"call 'refresh' before accessing beans via the ApplicationContext");
}
return beanFactory;
}
这段方法中使用到的DefaultListableBeanFactory,是spring构造bean的核心类,非常重要,在后续springbean加载流程分析中会讲到这个类。
功能扩展
主要对以下几个方面进行扩展,具体细节暂不展开
- 增加对SpEL语言支持
- 增加对属性编辑器的支持
- 增加一些内置类,如果Aware实现类
- 设置了依赖功能可忽略的接口
- 注册一些固定依赖的属性
- 增加对AspectJ的支持
- 将相关环境变量以及属性注册已单例模式注册
AbstractApplicationContext.prepareBeanFactory()
/**
* 配置工厂的标准上下文特征
* 例如上下文的 ClassLoader 和后处理器
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 告诉内部 bean 工厂使用上下文类加载器
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 通过若干Aware的实现类进行上下文回调 配置bean factory
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 接口未在普通工厂中注册为可解析类型。 MessageSource 作为 bean 注册(并为自动装配找到)。
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// 将用于检测内部 bean 的早期后处理器注册为 ApplicationListener。
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// 检测 LoadTimeWeaver 如果找到准备织入
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// 为类型匹配设置一个临时 ClassLoader。
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// 注册一些默认的bean。
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());
}
}
关于这个方法中提到的Aware接口在 Spring Aware接口作用及原理 这篇博文中有讲解。
添加ApplicationContextAwareProcessor处理器
postProcessBeanFactory是一个抽象方法,根据最开始的类图可知,这里调用的AbstractRefreshableWebApplicationContext的实现。此方法的作用是 在标准初始化之后修改应用程序上下文的内部 bean 工厂;所有 bean 定义都将被加载,但还没有 bean 被实例化;这允许在某些 ApplicationContext 实现中注册特殊的 BeanPostProcessors 等。
AbstractRefreshableWebApplicationContext.postProcessBeanFactory
/**
* 在标准初始化之后修改应用程序上下文的内部 bean 工厂。
* 所有 bean 定义都将被加载,但还没有 bean 被实例化。
* 这允许在某些 ApplicationContext 实现中注册特殊的 BeanPostProcessors 等。
*/
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 添加了一个后置处理器,ServletContextAwareProcessor
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
// 注册到上下文对象中
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
}
BeanFactory后处理
Spring容器允许BeanFactoryPostProcessor在容器实际实例化任何其他的bean之前读取配置的元数据,同时可以进行修改。根据业务需要,可配置多个BeanFactoryPostProcessor,如我们在配置数据库连接池中可能会出现这样的配置内容,这里就是通过BeanFactoryPostProcessor的子类来实现替换效果的。
<bean id="DataSource" class="org.logicalcobwebs.proxool.ProxoolDataSource">
<property name="driver" value="${jdbc.driver}" />
<property name="driverUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
AbstractApplicationContext.invokeBeanFactoryPostProcessors()
/**
* 实例化并调用所有已注册的 BeanFactoryPostProcessor bean,如果给定,则尊重显式顺序。
* 必须在单例实例化之前调用。
*
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// getBeanFactoryPostProcessors 返回将应用于内部 BeanFactory 的 BeanFactoryPostProcessor 列表。默认情况是空的
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// 同时处理 LoadTimeWeaver
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
初始化消息源
initMessageSource()
/**
* 初始化消息源。
* 如果没有在此上下文中定义,则使用父级。
*/
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// beanFactory中是否有消息源对象
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
// 如果没有父 MessageSource,则仅将父上下文设置为父 MessageSource
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
if (logger.isTraceEnabled()) {
logger.trace("Using MessageSource [" + this.messageSource + "]");
}
}
else {
// beanFactory没有消息源对象,new一个空的
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isTraceEnabled()) {
logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
}
}
}
初始化ApplicationEventMulticaster
AbstractApplicationContext.initApplicationEventMulticaster()
/**
* 初始化 ApplicationEventMulticaster。
* 如果上下文中没有定义,则使用 SimpleApplicationEventMulticaster。
*/
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
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() + "]");
}
}
}
留给子类实现的onRefresh
AbstractRefreshableWebApplicationContext.onRefresh()
重写了父类AbstractApplicationContext的onRefresh()方法
@Override
protected void onRefresh() {
// 为当前应用程序上下文初始化 ThemeSource,
// 自动检测名为“themeSource”的 bean。如果没有找到这样的 bean,则将使用默认(空)ThemeSource。
this.themeSource = UiApplicationContextUtils.initThemeSource(this);
}
注册监听器
添加实现 ApplicationListener 作为侦听器的 bean。不影响其他监听器,可以添加而不是 bean。
AbstractApplicationContext.registerListeners()
protected void registerListeners() {
// 首先注册静态指定的监听器。
// Register statically specified listeners first.
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 不要在此处初始化 FactoryBeans:我们需要保留所有常规 bean, 未初始化让后处理器适用他们
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
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);
}
}
}
AbstractApplicationContext.finishBeanFactoryInitialization()
完成此上下文的 bean 工厂的初始化,初始化所有剩余的非懒加载的单例 bean,。
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 为此上下文初始化转换服务。
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));
}
// 如果没有 BeanFactoryPostProcessor,则注册一个默认的嵌入值解析器
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// 尽早初始化 LoadTimeWeaverAware bean,以便尽早注册它们的转换器。
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// 停止使用临时 ClassLoader 进行类型匹配。
beanFactory.setTempClassLoader(null);
// 允许缓存所有 bean 定义元数据,而不是期望进一步的更改。
beanFactory.freezeConfiguration();
// 实例化所有剩余的(非惰性初始化)单例。
// 这里用到的实际上还是 DefaultListableBeanFactory ,记住这个类,在bean初始化中非常重要
beanFactory.preInstantiateSingletons();
}
AbstractApplicationContext.finishRefresh()
如标记spring的活动状态等等。
protected void finishRefresh() {
// 清除上下文级别的资源缓存(例如扫描中的 ASM 元数据)。
clearResourceCaches();
// 为此上下文初始化生命周期处理器。
initLifecycleProcessor();
// 首先将刷新传播到生命周期处理器
getLifecycleProcessor().onRefresh();
// 发布最终事件
publishEvent(new ContextRefreshedEvent(this));
// 加入到beanView中,目前应该在测试阶段
LiveBeansView.registerApplicationContext(this);
}
重置缓存
AbstractApplicationContext.resetCommonCaches()
重置 Spring 的常见反射元数据缓存
protected void resetCommonCaches() {
ReflectionUtils.clearCache();
AnnotationUtils.clearCache();
ResolvableType.clearCache();
CachedIntrospectionResults.clearClassLoader(getClassLoader());
}
至此,ClassPathXmlApplicationContext已经创建完成。