新闻资讯
还搞不清Spring与Spring MVC容器之间的关系?
在使用Spring MVC的时候,标准的配置是如下这样的:
1.ContextLoaderListener配置:
<!-- Spring读取Spring的配置文件 -->
<context-param>
<!-- 名称 -->
<param-name>contextConfigLocation</param-name>
<!-- 文件的位置 -->
<param-value>classpath:application-context.xml</param-value>
</context-param>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>meipian</param-value>
</context-param>
<!-- Spring 的监听器配置 -->
<listener>
<!-- 在Spring-web包下 context -->
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>复制代码
2.DispatcherServlet的配置:
<servlet>
<servlet-name>meipian</servlet-name>
<!-- 配置SpringMVC核心控制器 -->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>meipian</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>复制代码
ContextLoaderListener监听器的作用就是启动Web容器时,自动装配ApplicationContext的配置信息。因为它实现了ServletContextListener这个接口,在web.xml配置这个监听器,启动容器时,就会执行其实现的方法。Spring
MVC的使用的容器是WebApplicationContext。那么他和ContextLoaderListener所初始化的ApplicationContext有什么关系呢?
可以从DispatcherServlet的初始化过程说起:DispatcherServlet拦截了所有的请求,所以访问任何一个接口都会初始化DispatcherServlet对象。
初始化DispatcherServlet只是做了一个很简单的事:
public DispatcherServlet() { super();
setDispatchOptionsRequest(true);
}复制代码
其父类FrameworkServlet初始化什么也没有:复制代码
public FrameworkServlet() {
}复制代码
然后是Tomcat会调用DispatcherServlet的初始化方法,在Servlet的生命周期中,仅执行一次init()方法。它是在服务器上封装Servlet时执行的。 Servlet。任何有多少可以访问的Servlet,都不会重复执行init()。别问我为什么会调用init方法,这是servlet的规范。DispatcherServlet的init方法是在父类FrameworkServlet的父类HttpServlet中实现的:
@Override
public final void init() throws ServletException { if (logger.isDebugEnabled()) {
logger.debug("Initializing servlet '" + getServletName() + "'");
} // Set bean properties from init parameters. try {
PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
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) {
logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex); throw ex;
} // Let subclasses do whatever initialization they like. initServletBean(); if (logger.isDebugEnabled()) {
logger.debug("Servlet '" + getServletName() + "' configured successfully");
}
}复制代码
会调用DispatcherServlet的initServletBean()方法就是初始化WebApplicationContext的方法。这个方法在其子类FrameServlet方法中实现:
@Override
protected final void initServletBean() throws ServletException {
getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'"); if (this.logger.isInfoEnabled()) { this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started");
}
long startTime = System.currentTimeMillis(); try { this.webApplicationContext = initWebApplicationContext(); //初始化WebApplicationContext对象 initFrameworkServlet();
} catch (ServletException ex) { this.logger.error("Context initialization failed", ex); throw ex;
} catch (RuntimeException ex) { this.logger.error("Context initialization failed", ex); throw ex;
} if (this.logger.isInfoEnabled()) {
long elapsedTime = System.currentTimeMillis() - startTime; this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed in " +
elapsedTime + " ms");
}
}复制代码
initWebApplicationContext方法如下所示:
protected WebApplicationContext initWebApplicationContext() {
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = null; if (this.webApplicationContext != null) { // A context instance was injected at construction time -> use it wac = this.webApplicationContext; if (wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac; if (!cwac.isActive()) { // The context has not yet been refreshed -> provide services such as // setting the parent context, setting the application context id, etc if (cwac.getParent() == null) { // The context instance was injected without an explicit parent -> set // the root application context (if any; may be null) as the parent cwac.setParent(rootContext);
}
configureAndRefreshWebApplicationContext(cwac);
}
}
} if (wac == null) { // No context instance was injected at construction time -> see if one // has been registered in the servlet context. If one exists, it is assumed // that the parent context (if any) has already been set and that the // user has performed any initialization such as setting the context id wac = findWebApplicationContext();
} if (wac == null) { // No context instance is defined for this servlet -> create a local one wac = createWebApplicationContext(rootContext);
} 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. onRefresh(wac);
} if (this.publishContext) { // Publish the context as a servlet context attribute. String attrName = getServletContextAttributeName();
getServletContext().setAttribute(attrName, wac); if (this.logger.isDebugEnabled()) { this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() + "' as ServletContext attribute with name [" + attrName + "]");
}
} return wac;
}复制代码
会默认走到createWebApplicationContext方法:复制代码
protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) {
Class<?> contextClass = getContextClass(); if (this.logger.isDebugEnabled()) { this.logger.debug("Servlet with name '" + getServletName() + "' will try to create custom WebApplicationContext context of class '" +
contextClass.getName() + "'" + ", using parent context [" + parent + "]");
} if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) { throw new ApplicationContextException( "Fatal initialization error in servlet with name '" + getServletName() + "': custom WebApplicationContext class [" + contextClass.getName() + "] is not of type ConfigurableWebApplicationContext");
}
ConfigurableWebApplicationContext wac =
(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
wac.setEnvironment(getEnvironment());
wac.setParent(parent);
wac.setConfigLocation(getContextConfigLocation());
configureAndRefreshWebApplicationContext(wac); return wac;
}复制代码
在有contexloaderListener的情况下,父母是空的。
在有contexloaderListener的情况下,发现父母不是空的。
而且在Spring MVC的配置中,如果您将服务的配置与mvc的配置写在一起,有没有contexloaderListener无所谓的。
这就说明了contexloaderListener作用是什么了。
回复列表