XmlWebApplicationContext 是使用最频繁的 WebApplicationContext,值得深入了解和学习
它既是 DispatcherServlet 的 (WebApplicationContext)默认策略,又是 ContextLoaderListener 创建 root WebApplicationContext(根容器,同时也是 DispatcherServlet 的 WebApplicationContext 的父容器)的默认策略
继承体系
1.初始化流程
此处参考 DispatcherServlet 其中一段初始化的源码,这是专门用来初始化 XmlWebApplicationContext 的,可作为模范代码去借鉴:查看 DispatcherServlet 的父类 FrameworkServlet 的 createWebApplicationContext(…) 方法源码
//初始化 WebApplicationContext
protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) {
//默认是 XmlWebApplicationContext
Class<?> contextClass = getContextClass();
if (this.logger.isDebugEnabled()) {
this.logger.debug("Servlet with name '" + getServletName() +
"' will try to create custom WebApplicationContext context of class '" +
contextClass.getName() + "'" + ", using parent context [" + parent + "]");
}
if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
throw new ApplicationContextException(
"Fatal initialization error in servlet with name '" + getServletName() +
"': custom WebApplicationContext class [" + contextClass.getName() +
"] is not of type ConfigurableWebApplicationContext");
}
//初始化:调用无参构造函数
ConfigurableWebApplicationContext wac =
(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
//设置环境参数
wac.setEnvironment(getEnvironment());
//设置父ApplicationContext(一般都为root ApplicationContext)
wac.setParent(parent);
//设置“配置文件路径”(在后续的“刷新”阶段才会加载XML配置)
wac.setConfigLocation(getContextConfigLocation());
//配置并“刷新”容器
configureAndRefreshWebApplicationContext(wac);
return wac;
}
//配置并“刷新”容器
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {
//设置一个更有用的并且唯一的 ApplicationContext id
if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
// The application context id is still set to its original default value
// -> assign a more useful id based on available information
if (this.contextId != null) {
wac.setId(this.contextId);
}
else {
// Generate default id...
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
ObjectUtils.getDisplayString(getServletContext().getContextPath()) + '/' + getServletName());
}
}
wac.setServletContext(getServletContext());
wac.setServletConfig(getServletConfig());
wac.setNamespace(getNamespace());
//此处注册一个监听器:当ApplicationContext进行“刷新”时,onApplicationEvent(..)方法将被回调,进而触发模板方法:onRefresh(..)
//身为子类的DispatcherServlet就是利用这一点,通过重写该模板方法,实现了各类组件初始化(包括HandlerMapping、HandlerAdapter、ViewResolver)
//各类组件的初始化策略中既存在默认策略,也允许自定义配置,了解其配置有助于了解SpringMVC体系架构,请自行查阅相关源码
wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));
// The wac environment's #initPropertySources will be called in any case when the context
// is refreshed; do it eagerly here to ensure servlet property sources are in place for
// use in any post-processing or initialization that occurs below prior to #refresh
ConfigurableEnvironment env = wac.getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig());
}
//模板回调方法,可由子类实现,用来修改WebApplicationContext配置信息
postProcessWebApplicationContext(wac);
//提供给ApplicationContextInitializer接口介入的机会,可用来修改WebApplicationContext配置信息
applyInitializers(wac);
//刷新ApplicationContext配置信息(包括加载XML资源、属性文件等)
wac.refresh();
}
可以看到,初始化 XmlWebApplicationContext 主要分为两阶段:(1)【配置阶段】设置各种重要属性,包括设置配置文件路径;(2)【刷新阶段】调用 XmlWebApplicationContext 的 refresh(),该方法涉及容器(或者说BeanFactory)的整个生命周期
【刷新阶段】:查看 refresh() 方法源码,该方法由 XmlWebApplicationContext 的父类 AbstractApplicationContext 实现
@Override
public void refresh() throws BeansException, IllegalStateException {
//加锁,同步ApplicationContext的“刷新”或“销毁”阶段
synchronized (this.startupShutdownMonitor) {
//“刷新”阶段的事前准备(比如启动计时、标记状态位等)
prepareRefresh();
//①刷新内部的BeanFactory(默认为DefaultListableBeanFactory)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//BeanFactory的准备阶段,配置一些重要属性(例如ClassLoader、post-processors)
prepareBeanFactory(beanFactory);
try {
//②模板方法,可由子类(AbstractRefreshableWebApplicationContext)重写
//(当前进度:BeanFactory里全部的Bean配置已加载,但未进行实例化)
postProcessBeanFactory(beanFactory);
//实例化BeanFactory里所有的BeanFactoryPostProcessor,并依据排序进行调用
//(开发者可据此配置一个自定义的BeanFactoryPostProcessor,以介入容器的生命周期)
invokeBeanFactoryPostProcessors(beanFactory);
//收集并注册BeanFactory里所有的BeanPostProcessor
//(开发者可据此配置一个自定义的BeanPostProcessor,以介入Bean的生命周期)
registerBeanPostProcessors(beanFactory);
//初始化 MessageSource(事件源)
initMessageSource();
//初始化 ApplicationEventMulticaster(应用事件多路广播)
initApplicationEventMulticaster();
//模板方法,可由子类重写(初始化ThemeSource)
//(当前进度:特殊的Bean已初始化完成,比如BeanPostProcessor,但singleton bean未进行实例化)
onRefresh();
//收集并注册所有的ApplicationListener,如果存在“提前事件”,将其广播出去
registerListeners();
//③实例化并缓存所有的singleton bean,除了延迟加载的
//(当前进度:内部BeanFactory已初始化完成)
finishBeanFactoryInitialization(beanFactory);
//最后一步,发布相应的事件
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();
}
}
}
以下针对细节部分展开描述,共3个
①刷新内部的BeanFactory(默认为DefaultListableBeanFactory):查看 obtainFreshBeanFactory() 方法源码
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//模板抽象方法,由子类实现(AbstractRefreshableApplicationContext)
refreshBeanFactory();
//获取“刷新”后的BeanFactory,
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
由上,查看 AbstractRefreshableApplicationContext 的 refreshBeanFactory() 方法源码
@Override
protected final void refreshBeanFactory() throws BeansException {
//销毁已存在的BeanFactory
if (hasBeanFactory()) {
//回收 singleton bean 缓存,方便GC
destroyBeans();
//设为null,方便GC
closeBeanFactory();
}
//创建并初始化一个新的 DefaultListableBeanFactory
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
//设置状态位,以允许重写BeanFactory配置
customizeBeanFactory(beanFactory);
//模板抽象方法(加载XML资源配置),由子类重写
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
②模板方法,可由子类重写(AbstractRefreshableWebApplicationContext):查看被重写的 postProcessBeanFactory(..) 方法源码
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
//注册ServletContextAwareProcessor,管理servletContext、servletConfig的依赖注入
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
//忽视ServletContextAware接口的默认依赖注入
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
//忽视ServletConfigAware接口的默认依赖注入
beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
//注册各种作用域的实现机制(比如request、session)
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
//收集并注册应用环境参数("contextParameters", "contextAttributes")
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
}
③实例化并缓存所有的singleton bean,除了延迟加载的:查看 AbstractApplicationContext 的 finishBeanFactoryInitialization(..) 方法源码
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 bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
@Override
public String resolveStringValue(String strVal) {
return getEnvironment().resolvePlaceholders(strVal);
}
});
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
//停止使用临时的类加载器
beanFactory.setTempClassLoader(null);
//冻结Bean配置信息,不再被修改,并支持进一步缓存
beanFactory.freezeConfiguration();
//确保实例化所有的singleton bean,除了延迟加载(懒加载)
//(singleton作用域的bean可支持缓存、SmartInitializingSingleton接口等)
beanFactory.preInstantiateSingletons();
}
2.查看getBean(String name)源码
查看 XmlWebApplicationContext 的 getBean(String name) 方法源码,该方法由父类 AbstractApplicationContext 实现
@Override
public Object getBean(String name) throws BeansException {
//验证内部的BeanFactory处于“激活”状态
assertBeanFactoryActive();
//默认采用的是 DefaultListableBeanFactory
return getBeanFactory().getBean(name);
}
后续流程可参考 DefaultListableBeanFactory 的 getBean(String name) 方法源码