Spring
源码 - 容器刷新obtainFreshBeanFactory()
Spring
版本:Spring 5.3.13-release
# 1、obtainFreshBeanFactory()
获取BeanFactory
obtainFreshBeanFactory()
为Spring
容器刷新的第二个方法,其字面意思为获取新鲜的Bean工厂。为AbstractApplicationContext
获取BeanFactory
使其具备Bean
的一些列基本操作能力。为后续的工作提供帮助。
AbstractApplicationContext#obtainFreshBeanFactory()
代码:
/**
* Tell the subclass to refresh the internal bean factory.
* @return the fresh BeanFactory instance
* @see #refreshBeanFactory()
* @see #getBeanFactory()
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 初始化 beanFactory, 并进行配置读取(XML 或配置类), 并将获取的 beanFactory 记录在当前实体的属性中
refreshBeanFactory();
// 返回当前实体的 beanFactory 属性
return getBeanFactory();
}
这里代码很清晰,Spring
将BeanFactory
的创建委派给refreshBeanFactory()
方法。refreshBeanFactory()
是AbstractApplicationContext
类中的抽象方法,这里使用委派模式,将BeanFactory
的创建委派给refreshBeanFactory()
方法,自己并不关心创建过程。
# 2、BeanFactory
的创建过程
AbstractApplicationContext#refreshBeanFactory()
方法被两个类实现AbstractRefreshableApplicationContext
和GenericApplicationContext
。
protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
# 1、GenericApplicationContext#refreshBeanFactory()
GenericApplicationContext#refreshBeanFactory()
代码片段:
private final DefaultListableBeanFactory beanFactory;
/**
* Create a new GenericApplicationContext.
* @see #registerBeanDefinition
* @see #refresh
*/
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
/**
* Create a new GenericApplicationContext with the given DefaultListableBeanFactory.
* @param beanFactory the DefaultListableBeanFactory instance to use for this context
* @see #registerBeanDefinition
* @see #refresh
*/
public GenericApplicationContext(DefaultListableBeanFactory beanFactory) {
Assert.notNull(beanFactory, "BeanFactory must not be null");
this.beanFactory = beanFactory;
}
/**
* Do nothing: We hold a single internal BeanFactory and rely on callers
* to register beans through our public methods (or the BeanFactory's).
* @see #registerBeanDefinition
*/
@Override
protected final void refreshBeanFactory() throws IllegalStateException {
// CAS 将容器刷新状态设置为 true
if (!this.refreshed.compareAndSet(false, true)) {
throw new IllegalStateException(
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
}
// 设置 beanFactory 的序列化 id
this.beanFactory.setSerializationId(getId());
}
GenericApplicationContext
中的操作很简单,只是将容器刷新状态设置为true
,然后设置BeanFactory
的序列化id
。
通过构造函数可以很清晰的看到,GenericApplicationContext
中的BeanFactory
类型为DefaultListableBeanFactory
,这也是Spring
默认的BeanFactory
。
# 2、AbstractRefreshableApplicationContext#refreshBeanFactory()
AbstractRefreshableApplicationContext#refreshBeanFactory()
代码片段:
/** Bean factory for this context. */
@Nullable
private volatile DefaultListableBeanFactory beanFactory;
/**
* 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 {
// 如果存在 BeanFactory 则销毁 BeanFactory
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 创建 DefaultListableBeanFactory 对象
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 为了序列化自指定 id, 可以从 id 反序列化获取到 BeanFactory 对象
beanFactory.setSerializationId(getId());
// 定制 BeanFactory, 设置相关属性, 包括是否允许覆盖同名称的不同定义的对象以及循环依赖
customizeBeanFactory(beanFactory);
// 初始化 DocumentReader, 并进行 XML 文件读取及解析, 默认命名空间的解析, 自定标签的解析
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
/**
* 创建 DefaultListableBeanFactory
*
* Create an internal bean factory for this context.
* Called for each {@link #refresh()} attempt.
* <p>The default implementation creates a
* {@link org.springframework.beans.factory.support.DefaultListableBeanFactory}
* with the {@linkplain #getInternalParentBeanFactory() internal bean factory} of this
* context's parent as parent bean factory. Can be overridden in subclasses,
* for example to customize DefaultListableBeanFactory's settings.
* @return the bean factory for this context
* @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowBeanDefinitionOverriding
* @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowEagerClassLoading
* @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowCircularReferences
* @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowRawInjectionDespiteWrapping
*/
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
- 首先判断是否有
BeanFactory
,如果有则先进行销毁。 - 通过
createBeanFactory()
方法创建BeanFactory
。createBeanFactory()
返回的也是DefaultListableBeanFactory
类型的BeanFactory
。 - 定制
BeanFactory
, 设置相关属性,包括是否允许覆盖同名称的不同定义的对象以及循环依赖。 - 初始化
DocumentReader
,并进行XML
文件读取及解析,默认命名空间的解析,自定标签的解析。
GitHub源码地址:https://github.com/kapbc/kapcb-spring-source/tree/master/Spring-Framework-v5.3.13
备注:此文为笔者学习
Spring
源码的笔记,鉴于本人技术有限,文中难免出现一些错误,感谢大家批评指正。