spring-context.xml
和 spring-servlet.xml
是两个具有父子关系的上下文配置。
1 定义不同
1.1 全局的上下文配置:spring-context.xml
- 顾名思义,应用上下文配置,定义了应用整体的上下文配置,这些上下文贯穿于整个应用,应用级别的配置。
- 多个
servlet
可以共享此配置
web.xml
中配置如下:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
ContextLoaderListener
是 Spring
的监听器,它的作用就是启动 Web
容器时,自动装配 ApplicationContext
的配置信息。因为它实现了 ServletContextListener
这个接口,在 web.xml
配置这个监听器,启动容器时,就会默认执行它实现的方法。
1.2 Servlet 级别的上下文配置:spring-servlet.xml
servlet
级别的配置,可以独立多个配置文件,一个应用中可以配置多个servlet
- 通常用于加载
controller
层需要的类,比如拦截器,mvc
标签加载的类
web.xml
中配置如下:
<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-servlet.xml</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
通过配置即可了解,spring-servlet.xml
其实就是指定的 org.springframework.web.servlet.DispatcherServlet
对应的 contextConfigLocation
参数。
注意:
servlet
中 <param-name>contextConfigLocation</param-name>
中对应的 contextConfigLocation
的配置和顶部(全局上下文)配置的
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-context.xml</param-value>
</context-param>
contextConfigLocation
的业务属性不同。一个是定义全局的上下文配置,一个是定义单独的 servlet
对应的上下文配置。
2 关系等级
Spring lets you define multiple contexts in a parent-child hierarchy.
The spring-context.xml defines the beans for the "root webapp context", i.e. the context associated with the webapp.
The spring-servlet.xml (or whatever else you call it) defines the beans for one servlet's app context.
There can be many of these in a webapp, one per Spring servlet (e.g. spring1-servlet.xml for servlet spring1, spring2-servlet.xml for servlet spring2).
Beans in spring-servlet.xml can reference beans in spring-context.xml, but not vice versa.
All Spring MVC controllers must go in the spring-servlet.xml context.
In most simple cases, the spring-context.xml context is unnecessary. It is generally used to contain beans that are shared between all servlets in a webapp. If you only have one servlet, then there's not really much point, unless you have a specific use for it.
通过官方文档的说明,即可以了解,这两者是具有父子关系
配置 | 关系 |
---|---|
spring-context.xml | 父亲 |
spring-servlet.xml | 儿子 |
要点:
- 一个
bean
如果在两个文件中都被定义了(比如两个文件中都定义了component scan
扫描相同的package
),spring
会在application context
和servlet context
中都生成一个实例,他们处于不同的上下文空间中,他们的行为方式是有可能不一样的。 - 如果
application context
和servlet context
中都存在同一个@Service
的实例,controller
(在servlet context
中) 通过@Resource
引用时, 会优先选择servlet context
中的实例。 servlet context
可以引用application context
里的实例,反之不可以- 多个
servlet
共享application context
里的实例 - 在
spring-context.xml
和spring-servlet.xml
定义的bean
最好不要重复,spring-servlet.xml
最好只定义扫描@controler
,而spring-context.xml
定义扫描其它的Bean
。
例如:
spring-context.xml
<context:component-scan base-package="com.test" use-default-filters="true">
<context:exclude-filter
type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
spring-servlet.xml
<context:component-scan base-package="com.test.controller" use-default-filters="false">
<context:include-filter
type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
解释:
use-default-filters
用来指示是否自动扫描带有@Component
、@Repository
、@Service
和@Controller
的类。默认为true
,即默认扫描<context:include-filter/>
子标签是用来添加扫描注解<context:exclude-filter/>
子标签是用来排除扫描注解