首先需要知道的是,ContextLoaderListener属于Spring框架,其实现了ContextLoaderListener接口,本质是一个listener,当服务启动,Context初始化和销毁时被调用;而DispatcherServlet,其继承了HttpServlet,本质是一个Servlet,Servlet初始化以及相关url访问时会被调用。
ContextLoaderListener会读取web.xml中定义的context-param标签,例如:
<!-- Context ConfigLocation -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/spring-context*.xml</param-value>
</context-param>
当然,你可以不定义,ContextLoaderListener会有一个默认的地址去寻找文件。ContextLoaderListener其主要功能是初始化Ioc容器,这样,我们在项目中管理bean容器就可以通过ApplicationContext实例化,而不必去new;还有,当你用到了Shiro 、Dubbo等其他需要Sping配置的框架,其需要在ContextLoaderListener中加载,因此需要定义在该文件下。当然也可以定义在后面提到的sping-mvc.xml文件中,但考虑到listener和servlet加载顺序,更推介定义在这里。(包括像一些定时调度任务等也可以定义在这里)
DispatcherServlet中常常见到的配置是:
<!-- MVC Servlet -->
<servlet>
<servlet-name>springServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/spring-mvc*.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
同样定义了contextConfigLocation参数,其中的内容大致为各个标签扫描的路径、视图文件解析等,总的来说是项目启动后,有人点进你的网站中进行具体操作时执行的一些步骤。
还有一点,这两者也牵扯到了Spring的父子容器的概念,其访问规则为:
子容器可以访问父容器的对象,而父容器不可以访问自容器的对象。
针对扫描的包的话,ContextLoaderListener扫描的包包括Dao、Service(aop增强),而DispatcherServlet其扫描的包主要为Controller。根据访问规则,我们就可以在Controller中实例化Service和Dao。不仅如此,也可以联想到Spring的前端表现框架不仅有SpringMVC,也可以是Struts2或其他框架,这样的父子容器设计,也可以让Spring有非常好的可扩展性。