SpringMVC源码 1 ContextLoaderListener和Servlet容器web.xml配置
1.先说下ServletContext
javaee标准规定了,servlet容器需要在应用项目启动时,给应用项目初始化一个ServletContext作为公共环境容器存放公共信息。ServletContext中的信息都是由容器提供的。
通过contextListener获取web.xml中的参数。<context-param>以及<listener>
1.servlet容器启动的时候,找到应用配置文件(web.xml)中的<context-param>作为键值对放到ServletContext中。
2.servlet容器读取<listener>节点,构建对应的listener,容器调用了
contextInitialized(ServletContextEvent event)方法,执行其中的操作。(所有Listener必须继承自ServletContextListener
)
<context-param>只是将上下文的键值对传入servletContext中,本身并没有什么实际意义,需要Listener对参数进行解析后才具有一定意义。其中param-name是规定的,有Listener中进行定义。例如定义了m-name,在配置文件中<param-name>也需要是m-name。
<listener> 初始化上下文的监听器。 <listener>是否可以设置多个???
答案是显然的,当然可以。
web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
//contextConfigLocation是在Spring的ContextLoader中定义的参数,确定Spring配置文件位置
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<context-param>
<param-name>m-name</param-name>
//m-name是在自己写的ServletContextListener实现类中定义的参数
<param-value>mname</param-value>
</context-param>
<context-param>
<param-name>contextId</param-name>
//contextId是在Spring的ContextLoader中定义的参数
<param-value>MMM-WebApplicationContext</param-value>
</context-param>
//如果想要在web程序初始化的时候使用ServletContextListener,就必须在web.xml中加入<listener>节点
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>com.XXX.MYContextListener</listener-class>
</listener>
public class MYContextListener implements ServletContextListener{
public static final String CONTEXT_NAME_PARAM = "m-name";
public static final String CONTEXT_CLASS_PARAM = "m-class";
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext context = sce.getServletContext();
String mname = (String) context.getInitParameter(CONTEXT_NAME_PARAM);
String mclass = context.getInitParameter(CONTEXT_CLASS_PARAM);
System.out.println(mname+" "+mclass);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
// TODO Auto-generated method stub
}
}
public class ContextLoaderListener extends ContextLoader implements ServletContextListener{
........
@Override
public void contextInitialized(ServletContextEvent event) {
initWebApplicationContext(event.getServletContext());
}
/**Close the root web application context.*/
@Override
public void contextDestroyed(ServletContextEvent event) {
closeWebApplicationContext(event.getServletContext());
ContextCleanupListener.cleanupAttributes(event.getServletContext());
}
}
其中spring需要的contextConfigLocation也是在spring中的ContextLoader.class中定义的
public static final String CONTEXT_ID_PARAM = "contextId";
public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation";
public static final String CONTEXT_CLASS_PARAM = "contextClass";等等等等 具体看后面的源码解释。
2.执行流程
web.xml在<context-param>标签中声明应用范围内的初始化参数
1.启动一个WEB项目的时候,容器(如:Tomcat)会去读它的配置文件web.xml.读两个节点: <listener>和 <context-param>
2.紧接着,容器创建一个ServletContext(上下文)。在该应用内全局共享。
3.容器将<context-param>转化为键值对,并交给ServletContext。有接下来的ServletContextListener去调用
4.容器创建<listener>中的类实例,即创建监听.该监听器必须实现自ServletContextListener接口。
可以定义多个listener,执行顺序按照web.xml中定义的顺序来执行。
5.在Listener中会有contextInitialized(ServletContextEvent event)初始化方法
在这个方法中获得ServletContext = ServletContextEvent.getServletContext();
String value = ServletContext.getInitParameter("<context-param name>");
6.得到这个context-param的值之后,你就可以做一些操作了.注意,这个时候你的WEB项目还没有完全启动完成.这个动作会比所有的Servlet都要早.
换句话说,这个时候,你对<context-param>中的键值做的操作,将在你的WEB项目完全启动之前被执行.只有在这个时候<context-param>中的参数才是有意义的(也只对相应的listener而言)。对于ServletContext来说只是一组String键值对
所有的servlet容器和listener监听类,都是同意按照java Servlet API来进行开发的。Package javax.servlet
3.ContextLoaderListener 和ContextLoader
项目中使用Spring 时,applicationContext.xml配置文件中并没有BeanFactory,要想在业务层中的class 文件中直接引用Spring容器管理的bean可通过以下方式
1、在web.xml配置监听器ContextLoaderListener。ContextLoaderListener的作用就是启动Web容器时,自动装配ApplicationContext的配置信息。因为