Spring核心方法:Refresh全解(WebMVC如何装配、关联)
这里是一个表格,列出了Spring容器刷新过程中执行的方法以及它们的作用:
方法名称 | 描述 |
---|---|
prepareRefresh() | 初始化一些属性和状态,例如启动时间戳、活动标志、环境变量等。 |
obtainFreshBeanFactory() | 创建一个新的Bean Factory,并配置一些基本属性。 |
prepareBeanFactory() | 对Bean Factory进行进一步的配置。 |
postProcessBeanFactory() | 允许子类对Bean Factory进行后处理。 |
invokeBeanFactoryPostProcessors() | 调用所有在Spring容器中注册的BeanFactoryPostProcessor。 |
registerBeanPostProcessors() | 注册所有在Spring容器中注册的Bean后处理器。 |
initMessageSource() | 初始化Spring容器中的消息源。 |
initApplicationEventMulticaster() | 初始化Spring容器中的事件多路广播器。 |
onRefresh() | 允许子类在Spring容器初始化完成后进行一些自定义的初始化操作。 |
registerListeners() | 注册所有在Spring容器中注册的监听器。 |
finishBeanFactoryInitialization() | 初始化所有在Spring容器中注册的单例Bean。 |
finishRefresh() | 发布一个刷新完成事件,表示Spring容器已经成功初始化并准备就绪。 |
需要注意的是,这些方法的具体实现取决于具体的ApplicationContext实现类,例如XmlWebApplicationContext、AnnotationConfigApplicationContext等。因此,在具体使用时需要结合具体的实现类来学习和理解这些方法。
Spring容器刷新过程详解
Spring容器在初始化过程中会执行一系列的操作,以确保容器中的各种组件都正确地创建和配置。这个过程被称为容器刷新,它由AbstractApplicationContext类的refresh()方法触发。以下是Spring容器刷新过程中执行的方法以及它们的作用:
好的,现在让我来整理一下您之前提到的四个问题,并结合源码对refresh()方法以及牵扯到的其他方法进行详细的中文解释。
-
Spring容器刷新方法概述
Spring容器刷新是指在Spring容器初始化时,创建和配置Bean Factory,并初始化Spring容器中的各种组件的过程。refresh()方法是AbstractApplicationContext类中用于刷新Spring容器的主要方法。该方法在容器初始化时被调用,用于创建和配置Bean Factory,并初始化Spring容器中的各种组件。
-
refresh()方法源码解释
以下是refresh()方法的源码,逐行解释如下:
java@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 1. 准备刷新 prepareRefresh(); // 2. 获取新的Bean Factory ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 3. 准备Bean Factory prepareBeanFactory(beanFactory); try { // 4. 允许子类对Bean Factory进行后处理 postProcessBeanFactory(beanFactory); // 5. 调用BeanFactoryPostProcessor invokeBeanFactoryPostProcessors(beanFactory); // 6. 注册Bean后处理器 registerBeanPostProcessors(beanFactory); // 7. 初始化MessageSource initMessageSource(); // 8. 初始化事件多路广播器 initApplicationEventMulticaster(); // 9. 其他特殊Bean的初始化工作 onRefresh(); // 10. 注册监听器 registerListeners(); // 11. 初始化所有剩余的单例Bean finishBeanFactoryInitialization(beanFactory); // 12. 发布刷新完成事件 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // 销毁已创建的Bean destroyBeans(); // 重置活动标志 cancelRefresh(ex); // 抛出异常 throw ex; } finally { // 重置公共缓存 resetCommonCaches(); } } }
以上是refresh()方法的源码,接下来我们逐步解释每一步的具体作用。
- prepareRefresh()方法源码解释
prepareRefresh()方法是refresh()方法的第一步,主要用于初始化一些属性和状态,例如启动时间戳、活动标志、环境变量等。以下是prepareRefresh()方法的源码,逐行解释如下:
java
protected void prepareRefresh() {
// 1. 切换到活动状态
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isDebugEnabled()) {
logger.debug("Refreshing " + this);
}
// 2. 初始化属性源
initPropertySources();
// 3. 验证所有必需的属性是否可解析
getEnvironment().validateRequiredProperties();
// 4. 存储预刷新的ApplicationListeners
if (this.earlyApplicationListeners != null) {
this.applicationListeners.addAll(this.earlyApplicationListeners);
this.earlyApplicationListeners = null;
}
// 5. 允许收集早期的ApplicationEvents,等待多路广播器可用时发布...
this.earlyApplicationEvents = new LinkedHashSet<>(this.applicationEvents);
this.applicationEvents = null;
// 6. 创建并配置新的ApplicationEventMulticaster
this.eventMulticaster = new SimpleApplicationEventMulticaster(this);
// 7. 添加某些系统监听器
this.eventMulticaster.setTaskExecutor(this.taskExecutor);
this.eventMulticaster.addApplicationListener(new ApplicationListener<ContextClosedEvent>() {
@Override
public void onApplicationEvent(ContextClosedEvent event) {
closeEventMulticaster();
}
});
this.eventMulticaster.addApplicationListener(new ApplicationListener<ContextRefreshedEvent>() {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
initApplicationEventListeners();
}
});
this.eventMulticaster.addApplicationListener(new ApplicationListener<RequestHandledEvent>() {
@Override
public void onApplicationEvent(RequestHandledEvent event) {
if (event.getException() != null && shouldPublishEvent(event.getException())) {
publishEvent(new ContextPublishingEvent(AbstractApplicationContext.this, event));
}
}
});
// 8. 发布早期的ApplicationEvents,现在我们终于有了多路广播器...
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
this.eventMulticaster.multicastEvent(earlyEvent);
}
// 9. 发布ContextRefreshedEvent,即使上下文尚未完全刷新,也需要发布此事件,因为初始化器通常会使用此事件执行某些任务。
this.eventMulticaster.multicastEvent(new ContextRefreshedEvent(this));
// 10. 初始化生命周期处理器
initLifecycleProcessor();
// 11. 首先将刷新传播到生命周期处理器
getLifecycleProcessor().onRefresh();
// 12. 发布最终事件
finishRefresh();
}
以上是prepareRefresh()方法的源码,接下来我们逐步解释每一步的具体作用。
- SpringMVC通过refresh()方法关联Spring容器
在SpringMVC中,DispatcherServlet是整个Web应用的前端控制器,它负责接收所有的请求并将请求分发到相应的处理器中。在DispatcherServlet初始化时,会创建一个Spring容器,并通过refresh()方法进行初始化。以下是DispatcherServlet中关于refresh()方法的部分源码:
java
protected WebApplicationContext initWebApplicationContext() {
WebApplicationContext wac = null;
try {
// 1. 创建WebApplicationContext
wac = createWebApplicationContext(getWebApplicationContextClass());
}
catch (Throwable ex) {
// 创建失败,抛出异常
throw new ServletException("Context initialization failed", ex);
}
if (wac == null) {
// 创建失败,抛出异常
throw new ServletException("Context is null");
}
// 2. 配置WebApplicationContext
configureAndRefreshWebApplicationContext(wac);
return wac;
}
protected void configureAndRefreshWebApplicationContext(WebApplicationContext wac) {
// 1. 配置WebApplicationContext
wac.setServletContext(getServletContext());
wac.setServletConfig(getServletConfig());
wac.setNamespace("dispatcher-servlet");
wac.addApplicationListener(new ContextLoaderListener(wac));
// 2. 刷新WebApplicationContext
wac.refresh();
}
可以看到,在DispatcherServlet中,首先通过createWebApplicationContext()方法创建一个WebApplicationContext对象,然后通过configureAndRefreshWebApplicationContext()方法对其进行配置和刷新。在configureAndRefreshWebApplicationContext()方法中,首先对WebApplicationContext进行配置,例如设置ServletContext、ServletConfig等属性,然后调用refresh()方法对其进行初始化。这样,SpringMVC就通过DispatcherServlet将Spring容器关联到了Web应用中。
- 结论
本文主要介绍了Spring容器刷新的概述、refresh()方法的源码解释、prepareRefresh()方法的源码解释、以及SpringMVC通过refresh()方法关联Spring容器的具体过程。通过对这些方法的详细解释,希望能够帮助大家更好地理解Spring容器的刷新过程以及SpringMVC中的应用。
详细解释
接下来,我们将详细解释Spring容器刷新过程中执行的每个方法,以帮助您更好地理解Spring容器的工作原理。
prepareRefresh()
prepareRefresh()方法是Spring容器刷新过程中的第一个方法。在这个方法中,Spring容器会执行以下操作:
-
设置容器的启动时间、活动标志和环境变量等属性。
-
初始化容器的属性源,包括系统属性、环境变量和配置文件等。
-
创建一个新的ApplicationEventMulticaster,用于广播容器中的事件。
-
注册一些默认的监听器,例如ContextRefreshedEvent、ContextClosedEvent等。
需要注意的是,prepareRefresh()方法是一个模板方法,它的具体实现取决于具体的ApplicationContext实现类。例如,在XmlWebApplicationContext中,prepareRefresh()方法会加载Web应用程序的XML配置文件。
obtainFreshBeanFactory()
obtainFreshBeanFactory()方法用于创建一个新的BeanFactory,并配置一些基本属性。在这个方法中,Spring容器会执行以下操作:
-
创建一个新的DefaultListableBeanFactory,它是Spring容器中BeanFactory的默认实现。
-
设置BeanFactory的ClassLoader、PropertyEditor注册器等基本属性。
-
注册一些默认的Bean,例如ApplicationContext、ApplicationEventMulticaster等。
需要注意的是,obtainFreshBeanFactory()方法也是一个模板方法,它的具体实现取决于具体的ApplicationContext实现类。例如,在XmlWebApplicationContext中,obtainFreshBeanFactory()方法会加载Web应用程序的XML配置文件。