返回
剖析Spring源码中的prepareRefresh()方法
后端
2024-02-04 08:44:01
Spring容器刷新流程概述
Spring容器的刷新是一个复杂的过程,涉及到众多组件的协同工作。容器刷新流程大致可分为以下几个步骤:
- 准备容器刷新(prepareRefresh):容器在刷新前需要进行一些准备工作,例如检查容器是否处于活动状态、是否有正在执行的任务等。
- 获取需要刷新的Bean(getRefreshBean):容器从上下文中获取需要刷新的Bean,这些Bean通常是那些在容器启动时创建的Bean。
- 关闭需要刷新的Bean(closeRefreshBeans):容器关闭需要刷新的Bean,释放它们持有的资源。
- 应用属性(applyProperties):容器将外部属性应用到需要刷新的Bean上。
- 初始化需要刷新的Bean(initializeRefreshBeans):容器初始化需要刷新的Bean,使其达到可用的状态。
- 完成容器刷新(finishBeanFactoryInitialization):容器完成对Bean的初始化,并执行其他必要的刷新操作,例如发布容器刷新事件等。
prepareRefresh()方法详解
prepareRefresh()方法是容器刷新流程的第一步,也是最关键的一步之一。该方法的主要任务是容器刷新前的准备工作,包括:
- 检查容器是否处于活动状态(isActive):容器在刷新前需要处于活动状态,如果容器处于非活动状态,则需要先将其激活。
- 检查是否有正在执行的任务(hasDestructionCallbacks):容器在刷新前需要确保没有正在执行的任务,如果有正在执行的任务,则需要先等待这些任务完成。
- 准备需要刷新的Bean(prepareRefreshBeans):容器为需要刷新的Bean做准备,包括将Bean的销毁回调函数标记为需要执行、将Bean的初始化回调函数标记为需要执行等。
prepareRefresh()方法的实现代码如下:
protected void prepareRefresh() {
synchronized (this.startupShutdownMonitor) {
// Check whether the context is still active.
if (this.active.get() == false) {
throw new IllegalStateException(
"Cannot call 'refresh' on a context that is already closed." +
" Call 'close' before 'refresh': context does not allow multiple refresh attempts: " + this);
}
// Check whether there is a running refresh in progress.
if (this.startupShutdownMonitor.isRunning()) {
throw new IllegalStateException(
"Cannot call 'prepareRefresh' while the context is being refreshed." +
" Consider defining a bean with an 'init-method' instead of a refresh callback: " + this);
}
this.startupShutdownMonitor.prepareRefresh();
// Initialize cancellation semaphore.
this.cancelRefresh = new LinkedBlockingQueue<>();
// Prepare beans for refresh.
try {
prepareRefreshBeans();
} catch (BeanDefinitionStoreException ex) {
// Trigger failure scenario.
throw new BeanCurrentlyInCreationException(ex.getBeanName(), ex);
}
// Initialize creation semaphore if necessary.
if (this.containsBeanFactory() && !containsSingleton("scopedTarget.scopedTargetFactoryBean")) {
this.creationBeanFactory = getBeanFactory();
}
// Allow for additional processing.
invokeBeanFactoryPostProcessors(BeanFactoryPostProcessor.POST_PROCESS_BEFORE_REFRESH);
// Prepare for bean definition validation.
this.beanDefinitionValidator = createBeanDefinitionValidator();
}
}
总结
prepareRefresh()方法是Spring容器刷新流程的第一步,也是最关键的一步之一。该方法的主要任务是容器刷新前的准备工作,包括检查容器是否处于活动状态、是否有正在执行的任务、准备需要刷新的Bean等。通过对prepareRefresh()方法的分析,我们可以更好地理解Spring容器的刷新过程,以及如何自定义容器的刷新行为。