Spring | spring-context.xml 和 spring-servlet.xml 的区别

342 阅读2分钟

spring-context.xmlspring-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>

ContextLoaderListenerSpring 的监听器,它的作用就是启动 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 contextservlet context 中都生成一个实例,他们处于不同的上下文空间中,他们的行为方式是有可能不一样的。
  • 如果 application contextservlet context 中都存在同一个 @Service 的实例,controller(在 servlet context 中) 通过 @Resource 引用时, 会优先选择 servlet context 中的实例。
  • servlet context 可以引用 application context 里的实例,反之不可以
  • 多个 servlet 共享 application context 里的实例
  • spring-context.xmlspring-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/> 子标签是用来排除扫描注解