上一篇介绍了refresh
方法的概览,其中包含12个方法,接下来我们就依照顺序依次聊一下每个方法所实现的功能以及如何实现的。这篇文章先介绍【prepareRefresh
】与【ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()
】。
1. prepareRefresh
方法
protected void prepareRefresh() {
// 记录容器启动的事件.
this.startupDate = System.currentTimeMillis();
// 设置对应的标志位
this.closed.set(false);
this.active.set(true);
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
// 扩展方法:本文使用的是AnnotationConfigApplicationContext进行创建容器因此在这里这个方法为空实现
initPropertySources();
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
// 这里我没有用到,所以暂时也没有具体看是做什么的,后续再补充吧!
getEnvironment().validateRequiredProperties();
// Store pre-refresh ApplicationListeners...
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
2. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()
这个方法也比较简单。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 刷新容器 2.1节介绍
refreshBeanFactory();
// 返回beanFactory 2.2节介绍
return getBeanFactory();
}
2.1 refreshBeanFactory()
protected final void refreshBeanFactory() throws IllegalStateException {
if (!this.refreshed.compareAndSet(false, true)) {
throw new IllegalStateException(
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
}
this.beanFactory.setSerializationId(getId());
}
这个方法就实现一个功能:为beanFactory
设置一个序列化Id
。
2.2 getBeanFactory()
public final ConfigurableListableBeanFactory getBeanFactory() {
return this.beanFactory;
}
这里为什么还要在refresh
里面再获取一下beanFactory
呢? 答案有点绕,
回顾一下在第一篇文章:Spring容器创建之this()(1)——AnnotatedBeanDefinitionReader中,我们在this()
里面,由于AnnotationConfigApplicationContext
类的父类是GenericApplicationContext
类,因此在有参构造器中调用this()时,首先执行父类GenericApplicationContext
类的构造器,然后
再执行GenericApplicationContext
类的父类AbstractBeanFactory
的构造器。其中在调用GenericApplicationContext
类的构造器的时候,执行的是:
private final DefaultListableBeanFactory beanFactory;
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
而在本篇文章2.1节中 refresh
方法所在的类为:AbstractApplicationContext
,他是GenericApplicationContext
的父类,因此无法获取GenericApplicationContext
中的beanFactory
,我们只能再调用refreshBeanFactory
方法使得AbstractApplicationContext
拥有beanFactory
。为了方便理解AbstractApplicationContext
、GenericApplicationContext
和AnnotationConfigApplicationContext
之间的关系,下面给出类图
3. 总结
prepareRefresh
方法:刷新前的预处理工作ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()
:将this()
方法中创建的beanFactory
暴露给refresh
方法所在的AbstractApplicaitonContext
类,这样该类中refresh
方法里的其他方法才可以使用beanFactory
。