这篇博客是前一篇博客Spring源码解读——Spring容器初始化 1的延续,在看这篇博客之前,最后先看一下前一篇
接着我们继续看WebApplicationContext的refresh()方法
先看一下他的顺序图
//AbstractApplicationContext XmlWebApplicationContext的父类
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备容器的更新
prepareRefresh();
// 告诉子类刷新内部bean工厂
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 配置factory的标准容器特征,包括classloader和postprocessor等
prepareBeanFactory(beanFactory);
try {
// 修改应用程序上下文的内部bean工厂标准后初始化。所有bean定义将被加载,但没有实例化bean。这允许在某些ApplicationContext实现类注册特殊BeanPostProcessors
postProcessBeanFactory(beanFactory);
// 实例化所有注册到BeanFactoryPostProcessor的bean,如果有次序,就按照次序实例化,必须在单例实例化之前
invokeBeanFactoryPostProcessors(beanFactory);
// 实例化并调用所有注册BeanPostProcessor的bean,如果有次序,就按照次序实例化。 必须在 application bean的实例化之前调用。
registerBeanPostProcessors(beanFactory);
// 实例化MessageSource()
initMessageSource();
// 实例化ApplicationEventMulticaster
initApplicationEventMulticaster();
// 实例化容器中特殊的类
onRefresh();
// 注册实现ApplicationListener的listener
registerListeners();
// 完成容器的beanFactory的实例化,初始化所有剩余单例bean
finishBeanFactoryInitialization(beanFactory);
//调用LifecycleProcessor的onRefresh()以及发布 org.springframework.context.event.ContextRefreshedEvent。
finishRefresh();
}
catch (BeansException ex) {
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
}
}
先看refresh()方法中的prepareBeanFactory()
//AbstractApplicationContext
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.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(EnvironmentAware.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);
// 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.
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());
}
}
这里都是为beanFactory(也就是DefaultListableBeanFactory)设置一些属性
我们再看一下ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();里面的操作
//AbstractApplicationContext
/**
* Tell the subclass to refresh the internal bean factory.
* @return the fresh BeanFactory instance
* @see #refreshBeanFactory()
* @see #getBeanFactory()
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory(); //创建一个DefaultListableBeanFactory,并加载类,实例化为对应的BeanDefinition
ConfigurableListableBeanFactory beanFactory = getBeanFactory(); //取得该DefaultListableBeanFactory,后面返回
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
我们在看一下refreshBeanFactory()
//AbstractRefreshableApplicationContext
/**
* This implementation performs an actual refresh of this context's underlying
* bean factory, shutting down the previous bean factory (if any) and
* initializing a fresh bean factory for the next phase of the context's lifecycle.
*/
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory(); //这里创建了一个DefaultListableBeanFactory,供后面实例化bean
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
我们在进入看loadBeanDefinitions()
//XmlWebApplicationContext
/**
* Loads the bean definitions via an XmlBeanDefinitionReader.
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
* @see #initBeanDefinitionReader
* @see #loadBeanDefinitions
*/
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// 这里为beanDefinitionReader配置容器的属性
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
initBeanDefinitionReader(beanDefinitionReader); //这个方法其实是空的,留给以后subclass去实现
loadBeanDefinitions(beanDefinitionReader); //这里开始加载BeanDefinition了
}
我们再进入loadBeanDefinitions()
//XmlWebApplicationContext
/**
* Load the bean definitions with the given XmlBeanDefinitionReader.
* <p>The lifecycle of the bean factory is handled by the refreshBeanFactory method;
* therefore this method is just supposed to load and/or register bean definitions.
* <p>Delegates to a ResourcePatternResolver for resolving location patterns
* into Resource instances.
* @throws java.io.IOException if the required XML document isn't found
* @see #refreshBeanFactory
* @see #getConfigLocations
* @see #getResources
* @see #getResourcePatternResolver
*/
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
String[] configLocations = getConfigLocations(); //这里开始读取配置文件了,就是我们之前的applicationContext.xml的配置文件了
if (configLocations != null) {
for (String configLocation : configLocations) {
reader.loadBeanDefinitions(configLocation); //这里就开始加载配置文件中的bean了,实例化成beandefinition
}
}
}
reader.loadBeanDefinitions(configLocation)
//AbstractBeanDefinitionReader
public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
}
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
int loadCount = loadBeanDefinitions(resources); //这里就是加载了,返回加载类的数目
if (actualResources != null) {
for (Resource resource : resources) {
actualResources.add(resource);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
}
return loadCount;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
else {
// Can only load single resources by absolute URL.
Resource resource = resourceLoader.getResource(location);
int loadCount = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
}
return loadCount;
}
}
接着我们再看refresh()中的invokeBeanFactoryPostProcessors()
他最后交给DefaultListableBeanFactory去实例话那些注册到BeanFactoryPostProcessor的那些类
//DefaultListableBeanFactory
private String[] doGetBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
List<String> result = new ArrayList<String>();
// 获得之前加载的类名
String[] beanDefinitionNames = getBeanDefinitionNames();
for (String beanName : beanDefinitionNames) {//遍历之前加载的全部类,并从中找出注册到BeanFactoryPostProcessor的那些类,把他们加入到result,为下面实例化
// Only consider bean as eligible if the bean name
// is not defined as alias for some other bean.
if (!isAlias(beanName)) {
try {
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// Only check bean definition if it is complete.
if (!mbd.isAbstract() && (allowEagerInit ||
((mbd.hasBeanClass() || !mbd.isLazyInit() || this.allowEagerClassLoading)) &&
!requiresEagerInitForType(mbd.getFactoryBeanName()))) {
// In case of FactoryBean, match object created by FactoryBean.
boolean isFactoryBean = isFactoryBean(beanName, mbd);
boolean matchFound = (allowEagerInit || !isFactoryBean || containsSingleton(beanName)) &&
(includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type);
if (!matchFound && isFactoryBean) {
// In case of FactoryBean, try to match FactoryBean instance itself next.
beanName = FACTORY_BEAN_PREFIX + beanName;
matchFound = (includeNonSingletons || mbd.isSingleton()) && isTypeMatch(beanName, type);
}
if (matchFound) {
result.add(beanName);
}
}
}
catch (CannotLoadBeanClassException ex) {
if (allowEagerInit) {
throw ex;
}
// Probably contains a placeholder: let's ignore it for type matching purposes.
if (this.logger.isDebugEnabled()) {
this.logger.debug("Ignoring bean class loading failure for bean '" + beanName + "'", ex);
}
onSuppressedException(ex);
}
catch (BeanDefinitionStoreException ex) {
if (allowEagerInit) {
throw ex;
}
// Probably contains a placeholder: let's ignore it for type matching purposes.
if (this.logger.isDebugEnabled()) {
this.logger.debug("Ignoring unresolvable metadata in bean definition '" + beanName + "'", ex);
}
onSuppressedException(ex);
}
}
}
这里,后面的refresh()的registerBeanPostProcessors(beanFactory)实例化过程是和之前的invokeBeanFactoryPostProcessors()一样的。
我们再来看refresh()的initMessageSource()
//AbstractApplicationContext
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) { //如果配置文件applicationContext.xml有配置messageSource,就根据配置文件实例化
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// Make MessageSource aware of parent MessageSource.
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
// Only set parent context as parent MessageSource if no parent MessageSource
// registered already.
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
if (logger.isDebugEnabled()) {
logger.debug("Using MessageSource [" + this.messageSource + "]");
}
}
else {
// Use empty MessageSource to be able to accept getMessage calls.
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
"': using default [" + this.messageSource + "]");
}
}
}
这里就是根据我们在配置文件applicationContext.xml中的时候有messagesource的配置,有的话就是实例化,没有的话就实例化一个DelegatingMessageSource,再把他设置到容器,在把他注册到单例集合中
接着,refresh()的initApplicationEventMulticaster()就是初始化ApplicationEventMulticaster。如果我们自己没有配置自定义的ApplicationEventMulticaster那就使用SimpleApplicationEventMulticaster
实例化思路还是和实例化messageSource差不多,都是从配置文件优先,如果没有明确配置就用默认的
接着,我们再来看refresh()的registerListener(),他就是先注册静态的容器本来级就应该有的类,然后在从我们之前加载的类中筛选listener,帅选实例化过程和之前的invokeBeanFactoryPostProcessors()实例化过程是一样的,接着在把listener加入到上面实例化的ApplicationEventMulticaster(它其实就是一个listener容器)中
//AbstractApplicationContext
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!
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String lisName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(lisName);
}
}
接着就是refresh()的finishBeanFactoryInitialization()
//AbstractApplicationContext
/**
* Finish the initialization of this context's bean factory,
* initializing all remaining singleton beans.
*/
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));
}
// 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);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// 允许缓存所有将不会被修改或进一步后期处理的bean定义元数据
beanFactory.freezeConfiguration();
// 实例化所有剩下的单例bean
beanFactory.preInstantiateSingletons();
}
再接着,refresh()的finishRefresh()
最后回到上篇博客中的initWebApplicationContext中
//ClassLoader
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
throw new IllegalStateException(
"Cannot initialize context because there is already a root application context present - " +
"check whether you have multiple ContextLoader* definitions in your web.xml!");
}
Log logger = LogFactory.getLog(ContextLoader.class);
servletContext.log("Initializing Spring root WebApplicationContext");
if (logger.isInfoEnabled()) {
logger.info("Root WebApplicationContext: initialization started");
}
long startTime = System.currentTimeMillis();
try {
// Store context in local instance variable, to guarantee that
// it is available on ServletContext shutdown.
if (this.context == null) {
this.context = createWebApplicationContext(servletContext);
}
if (this.context instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
if (!cwac.isActive()) {
// The context has not yet been refreshed -> provide services such as
// setting the parent context, setting the application context id, etc
if (cwac.getParent() == null) {
// The context instance was injected without an explicit parent ->
// determine parent for root web application context, if any.
ApplicationContext parent = loadParentContext(servletContext);
cwac.setParent(parent);
}
configureAndRefreshWebApplicationContext(cwac, servletContext);
}
}
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
if (ccl == ContextLoader.class.getClassLoader()) {
currentContext = this.context;
}
else if (ccl != null) {
currentContextPerThread.put(ccl, this.context);
}
if (logger.isDebugEnabled()) {
logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
}
if (logger.isInfoEnabled()) {
long elapsedTime = System.currentTimeMillis() - startTime;
logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
}
return this.context;
}
catch (RuntimeException ex) {
logger.error("Context initialization failed", ex);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
throw ex;
}
catch (Error err) {
logger.error("Context initialization failed", err);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);
throw err;
}
}
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); 将容器设置为ServletContext的属性,之前我们已经这是了ServletContext作为WebApplicationContext的属性,于是,两者相关联,可以通过ServletContext.getAttribute(
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE)获得容器
自此,Spring容器创建完毕