专题六:Spring源码之初始化容器BeanFactory
上一篇咱们通过一个例子介绍初始化容器上下文相关内容,并通过两个示例代码看到了Spring在设计阶段为我预留的扩展点,和我们应该如何利用这两个扩展点在Spring初始化容器上下文阶段为我们提供服务。这一篇咱们接着往下看。
上一篇咱们通过一个例子介绍初始化容器上下文相关内容,并通过两个示例代码看到了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
今日小结
通过对 `refresh` 方法中第二个核心方法 `obtainBeanFactory` 的解读,我们了解到通过 `createBeanFactory` 创建了 Spring 的初级容器,并定义了容器的两个核心参数:是否允许循环引用和是否允许覆盖。
我们还介绍了初级容器 `DefaultListableBeanFactory` 的类图,对 Spring 初级容器的初始化和结构有了初步了解。下一篇文章中,我们将开始讨论容器第一个重要成员:BeanDefiniton。
源码整体进度
目前整体进度梳理如下:
Spring框架中容器初始化的核心步骤和概念的概述:
-
初始化时间与容器状态:这是容器启动和初始化过程中需要考虑的基础属性。
-
构造方法:容器的构造方法开始整个初始化过程。
-
ClassPathXmlApplicationContext:这是一个用于从类路径下的XML配置文件中加载Spring应用上下文的特定实现。
-
初始化容器上下文环境:在容器启动时,需要设置和初始化容器的上下文环境。
-
属性值替换占位符:在配置文件中,可能包含一些占位符,需要在启动时被实际的属性值所替换。
-
prepareRefresh方法:这个方法在刷新容器之前被调用,用于准备刷新操作,例如设置早期的事件多播器。
-
PathMatchingResourcePatternResolver(this)实例:创建一个资源模式解析器实例,用于解析和匹配资源路径。
-
检测指定环境变量是否配置:检查环境变量是否已经设置,这可能影响资源的定位和加载。
-
resolvePath解析构造方法传入文件路径的占位符$0:解析传入的文件路径,并替换其中的占位符。
-
初始化初级容器:创建
DefaultListableBeanFactory
实例,这是Spring容器的基础,用于管理Bean的定义和生命周期。 -
调用obtainBeanFactory方法:这个方法用于获取或创建Bean工厂,它是容器的核心组件。
-
customizeBeanFactory方法:允许对Bean工厂进行定制,例如设置是否允许循环引用或覆盖。
-
loadBeanDefinitions:加载Bean定义,这可能来自XML配置文件、注解或其他源。
更多推荐
所有评论(0)