上一篇咱们通过一个例子介绍初始化容器上下文相关内容,并通过两个示例代码看到了Spring在设计阶段为我预留的扩展点,和我们应该如何利用这两个扩展点在Spring初始化容器上下文阶段为我们提供服务。这一篇咱们接着往下看。
老这样子下回到refresh方法上来:
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、解析类Xml、初始化BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 这一步主要是对初级容器的基础设计
// Prepare the bean factory for use in this context. 3、准备BeanFactory内容:
prepareBeanFactory(beanFactory); // 对beanFactory容器的功能的扩展:
try {
// Allows post-processing of the bean factory in context subclasses. 4、扩展点加一:空实现,主要用于处理特殊Bean的后置处理器
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context. 5、spring bean容器的后置处理器
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation. 6、注册bean的后置处理器
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context. 7、初始化消息源
initMessageSource();
// Initialize event multicaster for this context. 8、初始化事件广播器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses. 9、扩展点加一:空实现;主要是在实例化之前做些bean初始化扩展
onRefresh();
// Check for listener beans and register them. 10、初始化监听器
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons. 11、实例化:非兰加载Bean
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...
resetCommonCaches();
}
}
}
obtainFreshBeanFactory
让聚焦到obtainFreshBeanFactory方法,根据名称和注释简单猜测下这个方法是获取一个新的beanFactory容器。接下我们进入obtainFreshBeanFactory:
/**
* Tell the subclass to refresh the internal bean factory.
* @return the fresh BeanFactory instance
* @see #refreshBeanFactory()
* @see #getBeanFactory()
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 1、 new 一个DefaultListableBeanFactory实例,创建Spring初级容器、
// 2、设置容器是否允许循环依赖、覆盖;
// 3、解析xml生成BeanDefinition对象放入beanDefinitionMap容器
refreshBeanFactory();
// 获取ConfigurableListableBeanFactory方法
return getBeanFactory();
}
obtainFreshBeanFactory只有两个方法且getBeanFactory方法只是将成员变量this.beanFactroy进行了返回,所以这方法的核心在refreshBeanFactory。
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
synchronized (this.beanFactoryMonitor) {
if (this.beanFactory == null) {
throw new IllegalStateException("BeanFactory not initialized or already closed - " +
"call 'refresh' before accessing beans via the ApplicationContext");
}
return this.beanFactory;
}
}
refreshBeanFactory
接下来我们进入refreshBeanFactory方法中看下具体逻辑:
/**
* 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 {
// new 一个DefaultListableBeanFactory实例,创建Spring初级容器
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
// 定制容器参数:allowBeanDefinitionOverriding 是否允许被覆盖、allowCircularReferences 是否允许循环引用
customizeBeanFactory(beanFactory);
// 开始解析并加载xml文件中的bean,将解析后的BeanDefinition放入beanDefinitionMap容器中
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
可以看到我们上述的猜测正确的,Spring是在refreshBeanFacotry设置成员属性beanFactory,这个后面getBeanFacotry方法才可以通过成员属性获取到,再回到refreshBeanFacotry方法中。在我们进入方法的时候先是一个判断,因为第一次进去所以直接看try-catch代码块内容。
看下第一个行代码:
createBeanFactory返回一个DefaultListableBeanFactory实力对象,看到这个对象我们还是不得不提一下他的类图。
DefaultListableBeanFactory类图
在Spring中,BeanFactory是核心接口,负责实例化、配置和管理bean的生命周期。
类图结构分析
BeanFactory
- 所有Spring容器的根接口,定义了Spring容器的基本行为。
ListableBeanFactory
- 继承自BeanFactory,增加了列出所有bean定义的功能。
ConfigurableBeanFactory
- 提供了对BeanFactory的额外配置能力,如设置类加载器和属性编辑器。
SingletonBeanRegistry
- 接口,用于注册和管理单例bean。
DefaultSingletonBeanRegistry
- SingletonBeanRegistry接口的默认实现,负责注册和解析单例bean。
HierarchicalBeanFactory
- 允许BeanFactory形成层级结构,父工厂可以被子工厂继承。
AbstractBeanFactory
- 抽象类,提供了BeanFactory接口的默认实现。
AbstractAutowireCapableBeanFactory
- 抽象类,扩展了AbstractBeanFactory,增加了自动装配功能。
ConfigurableListableBeanFactory
- 继承自ConfigurableBeanFactory和ListableBeanFactory,提供了更多配置和bean列表功能。
DefaultListableBeanFactory
- 具体的BeanFactory实现,继承自AbstractAutowireCapableBeanFactory和ConfigurableListableBeanFactory,是Spring中最常用的bean工厂实现。
介绍完DefaultListableBeanFactory类图接着往下看。
定制容器参数:allowBeanDefinitionOverriding 是否允许被覆盖allowCircularReferences 是否允许循环引用,这两个参数后面我们会重点关注,在Bean实例化的时候,这这里咱们就留一个印象。接下来接着看
记载Xml中的BeanDefinition
进入loadBeanDefinitions方法
/**
* 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
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's resource loading environment.
// 配置BeanDefinition上下文信息
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,then proceed with actually loading the bean definitions.
// 看到规律了呢,Allow a subclass 基本上都是Spring 预留的扩展点,空实现,留给子类自己去自定义
initBeanDefinitionReader(beanDefinitionReader);
// 通过beanDefinitionReader去加载解析xml中的BeanDefinition
loadBeanDefinitions(beanDefinitionReader);
}