SpringMVC启动流程
SpringMVC启动流程
文章目录
- SpringMVC启动流程
- 1.启动前的相关配置
- 2.启动流程
- 1.启动tomcat容器
- 2.创建spring容器
- 3.创建springmvc容器
1.启动前的相关配置
- spring容器相关配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.anyi"></context:component-scan><bean id="user" class="com.anyi.beans.User"><property name="username" value="anyi"></property><property name="password" value="123"></property></bean>
</beans>
- springmvc容器相关配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"></beans>
- web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring-config.xml</param-value></context-param><servlet><servlet-name>mvc-test</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>mvc-test</servlet-name><url-pattern>/</url-pattern></servlet-mapping><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>
</web-app>
2.启动流程
1.启动tomcat容器
使用idea会自动启动tomcat容器,调用spring容器的初始化方法
2.创建spring容器
- 在初始化tomcat容器之前,必须先启动tomcat容器,启动之后tomcat会调用初始化方法initWebApplicationContext()来对容器进行初始化
@Override
public void contextInitialized(ServletContextEvent event) {// 初始化web容器,先开始初始化的spring容器initWebApplicationContext(event.getServletContext());
}
- 在这里会调用configureAndRefreshWebApplicationContext() 方法来进行spring容器的初始化
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {// 设置一个容器idif (ObjectUtils.identityToString(wac).equals(wac.getId())) {// The application context id is still set to its original default value// -> assign a more useful id based on available informationString idParam = sc.getInitParameter(CONTEXT_ID_PARAM);if (idParam != null) {wac.setId(idParam);}else {// Generate default id...wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +ObjectUtils.getDisplayString(sc.getContextPath()));}}// 设置servlet上下文wac.setServletContext(sc);String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);if (configLocationParam != null) {// 设置spring配置文件路径wac.setConfigLocation(configLocationParam);}// The wac environment's #initPropertySources will be called in any case when the context// is refreshed; do it eagerly here to ensure servlet property sources are in place for// use in any post-processing or initialization that occurs below prior to #refresh// 设置一些环境对象ConfigurableEnvironment env = wac.getEnvironment();if (env instanceof ConfigurableWebEnvironment) {((ConfigurableWebEnvironment) env).initPropertySources(sc, null);}// 可以定制化contextcustomizeContext(sc, wac);// 调用刷新方法wac.refresh();
}
- 刷新完成后,就完成了spring容器的初始化
3.创建springmvc容器
上述完成了tomcat、spring容器的创建和启动,接下来就是springmvc容器的启动了,而springmvc中最重要的就是Servlet,而Servlet的生命周期包含三个init、service、destroy。
- init方法调用是在DispatcherServlet的父类HttpServletBean中调用init()方法
@Override
public final void init() throws ServletException {// 调用初始化springmvc容器// Set bean properties from init parameters.// 从web.xml中获取servlet的配置文件PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);if (!pvs.isEmpty()) {try {BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));initBeanWrapper(bw);bw.setPropertyValues(pvs, true);}catch (BeansException ex) {if (logger.isErrorEnabled()) {logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);}throw ex;}}// 初始化ServletBean// Let subclasses do whatever initialization they like.initServletBean();
}
- 在initServletBean方法中会调用initWebApplicationContext()来进行springmvc容器的初始化
protected WebApplicationContext initWebApplicationContext() {// 获取父容器WebApplicationContext rootContext =WebApplicationContextUtils.getWebApplicationContext(getServletContext());WebApplicationContext wac = null;...// 进行容器刷新configureAndRefreshWebApplicationContext(cwac);// 判断是否有事件发布if (!this.refreshEventReceived) {// Either the context is not a ConfigurableApplicationContext with refresh// support or the context injected at construction time had already been// refreshed -> trigger initial onRefresh manually here.synchronized (this.onRefreshMonitor) {onRefresh(wac);}}...return wac;
}
- 调用configureAndRefreshWebApplicationContext()方法来刷新容器
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {// id 验证...// 设置一些属性值wac.setServletContext(getServletContext());wac.setServletConfig(getServletConfig());wac.setNamespace(getNamespace());// 放入一个ContextRefreshListener监听器wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));// The wac environment's #initPropertySources will be called in any case when the context// is refreshed; do it eagerly here to ensure servlet property sources are in place for// use in any post-processing or initialization that occurs below prior to #refreshConfigurableEnvironment env = wac.getEnvironment();if (env instanceof ConfigurableWebEnvironment) {((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig());}// 可以进行拓展修改postProcessWebApplicationContext(wac);// 设置一些初始化器applyInitializers(wac);// 开始容器刷新wac.refresh();
}
- 调用AbstractApplicationContext类中的refresh()方法来创建BeanFactory等容器刷新工作,详细见spring篇
- 在完成刷新后回到用一个方法finishRefresh()
protected void finishRefresh() {// Clear context-level resource caches (such as ASM metadata from scanning).// 清理缓存clearResourceCaches();// Initialize lifecycle processor for this context.// 实例化生命周期处理器initLifecycleProcessor();// Propagate refresh to lifecycle processor first.getLifecycleProcessor().onRefresh();// Publish the final event.// 发布事件publishEvent(new ContextRefreshedEvent(this));// Participate in LiveBeansView MBean, if active.LiveBeansView.registerApplicationContext(this);
}
- 这里会调用publishEvent()方法,由多播器来广播发布一个容器已经完成刷新的事件,会调用具体的监听器来进行处理。
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {...// Multicast right now if possible - or lazily once the multicaster is initializedif (this.earlyApplicationEvents != null) {this.earlyApplicationEvents.add(applicationEvent);}else {// 调用多播器广播事件,让监听器来处理getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);}...
}
- 遍历所有的监听器,最终会由我们前面注册的一个ContextRefreshListener监听器来进行处理,最终会调用他的onApplicationEvent方法
public void onApplicationEvent(ContextRefreshedEvent event) {this.refreshEventReceived = true;synchronized (this.onRefreshMonitor) {onRefresh(event.getApplicationContext());}
}
- 调用DispatcherServlet类中onRefresh(event.getApplicationContext())方法来完成springmvc九大模块的实例化
- 初始化 MultipartResolver:主要用来处理文件上传
- 初始化 LocaleResolver:主要用来处理国际化配置,基于URL参数的配置(AcceptHeaderLocaleResolver)
- 初始化 ThemeResolver:主要用来设置主题
- 初始化 HandlerMappings:映射器,用来完成request和controller的对应
- 初始化 HandlerAdapters:处理适配器,主要包含Http请求处理适配器,简单控制处理适配器,注解方法处理适配器
- 初始化 HandlerExceptionResolvers:基于HandlerExceptionResolver接口的异常处理
- 初始化RequestToViewNameTranslator:当controller处理器方法没有返回一个View对象或者逻辑视图名称,并且方法中没有直接往response的输入流中写入数据的时候
- 初始化 ViewResolvers:将ModelAndView选择合适的视图进行渲染处理器
- 初始化 FlashMapManager:提供请求存储属性,可供其他请求使用
@Override
protected void onRefresh(ApplicationContext context) {initStrategies(context);
}/*** Initialize the strategy objects that this servlet uses.* <p>May be overridden in subclasses in order to initialize further strategy objects.*/
protected void initStrategies(ApplicationContext context) {// 初始化 MultipartResolver:主要用来处理文件上传initMultipartResolver(context);// 初始化 LocaleResolver:主要用来处理国际化配置,基于URL参数的配置(AcceptHeaderLocaleResolver)initLocaleResolver(context);// 初始化 ThemeResolver:主要用来设置主题initThemeResolver(context);// 初始化 HandlerMappings:映射器,用来完成request和controller的对应initHandlerMappings(context);// 初始化 HandlerAdapters:处理适配器,主要包含Http请求处理适配器,简单控制处理适配器,注解方法处理适配器initHandlerAdapters(context);// 初始化 HandlerExceptionResolvers:基于HandlerExceptionResolver接口的异常处理initHandlerExceptionResolvers(context);// 初始化RequestToViewNameTranslator:当controller处理器方法没有返回一个View对象或者逻辑视图名称,并且方法中没有直接往response的输入流中写入数据的时候initRequestToViewNameTranslator(context);// 初始化 ViewResolvers:将ModelAndView选择合适的视图进行渲染处理器initViewResolvers(context);// 初始化 FlashMapManager:提供请求存储属性,可供其他请求使用initFlashMapManager:(context);
}
- 至此完成springmvc的所有启动流程,可以等待请求进入了。