zoukankan      html  css  js  c++  java
  • spring学习(五)--spring初始化配置

    从上一篇可以看出,tomcat在启动项目的时候,通过ContextLoaderListener监听器和DispatcherServlet分别初始化了service层的bean和controller层的bean。

    那么通过ContextLoaderListener和DispatcherServlet启动spring有什么区别呢?

    ContextLoaderListener监听器在spring-web包内,需要引入spring-web包。DispatcherServlet在spring-webmvc包内,需要引入spring-webmvc包。

        <!-- spring使用listener初始化bean(service和dao层bean) -->
        <!-- contextConfigLocation指定上下文文件位置,该项配置为全局配置,
               多个xml文件中间用逗号隔开,此项如果不配置,ContextLoaderListener默认取WEB-INF:applicationContext.xml -->
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springConfig/spring-beans.xml</param-value>
        </context-param>
        <!-- spring使用listener初始化bean(service和dao层bean) -->
        <listener>
              <listener-class>
                  org.springframework.web.context.ContextLoaderListener
              </listener-class>
        </listener>
    
        <!-- spring使用servlet初始化bean(controller层bean) -->
        <servlet>
            <servlet-name>DispatcherServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!-- init-param指定DispatcherServlet上下文配置文件的位置,为局部配置文件,只对DispatcherServlet有用
                 如果没有配置init-param,会默认读取/WEB-INF/${servlet-name}-servlet.xml -->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springConfig/spring-controllers.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>DispatcherServlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>

    1、spring原意是跟web不相关的bean,通过ContextLoaderListener初始化;跟web相关的bean,通过DispatcherServlet初始化。

    2、ContextLoaderListener默认读取/WEB-INF/applicationContext.xml,可以通过context-param标签指定ContextLoaderListener读取配置文件位置,context-param配置为全局变量。

       DispatcherServlet默认读取/WEB-INF/${servlet-name}-servlet.xml,可以通过标签init-param指定读取配置文件位置,init-param为局部变量,只供DispatcherServlet使用。

    3、如果context-param和init-param加载的配置文件出现重复,那么重复的配置文件中定义的bean就会被初始化两次,分别存在两个上下文中。这两个上下文并不是合并互补的,而是互不干扰的。虽然看似所有的bean都被初始化到容器上下文中,但如果配置有问题,还是会有一些bean不能正常工作。

    比如context-param文件下里的AOP声明式配置:

    <!--aop 行为-->
    <bean id="himvn" class="com.tangbao.hellomvn.Himvn" />
    <!--aop 注释方式-->
    <bean id="hiaspect" class="com.tangbao.hellomvn.Hiaspect" />
    <!--aop config-->
    <aop:aspectj-autoproxy />
    <aop:config>
        <aop:aspect id="aoplianxi" ref="himvn">
            <aop:pointcut id="test1" expression="execution(* com.tangbao.controller.RestlessController.RestlessController(..))"></aop:pointcut>
            <aop:before method="sayHi" pointcut-ref="test1"></aop:before>
            <aop:after method="sayHi" pointcut-ref="test1"></aop:after>
        </aop:aspect>
    </aop:config>

    假如此aop配置只在ContextLoaderListener中加载,没有在DispatcherServlet 中加载,那么此aop会无效。

    所以,在web项目中,可以不使用ContextLoaderListener和全局配置contextConfigLocation参数。把所有spring配置文件统一在DispatcherServlet下配置,所有bean都通过DispatcherServlet初始化,项目可以正常工作。

    此时,可以通过增加一个总的spring配置xml文件将其他xml文件引入,在web.xml中只添加该配置文件路径即可:

     spring-all.xml文件代码为:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns= "http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd ">
        
        <import resource="/spring-beans.xml" />
        <import resource="/spring-controllers.xml" />
    
    </beans>

    web.xml代码为(把contextLoaderListener去掉,DispatcherServlet中只配置spring-all.xml):

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
            xmlns="http://java.sun.com/xml/ns/javaee" 
            xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
            id="WebApp_ID" version="3.0">
    
        <!-- spring使用listener初始化bean(service和dao层bean) -->
        <!-- contextConfigLocation指定上下文文件位置,该项配置为全局配置,
               多个xml文件中间用逗号隔开,此项如果不配置,ContextLoaderListener默认取WEB-INF:applicationContext.xml -->
        <!-- <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springConfig/spring-beans.xml</param-value>
        </context-param> -->
        <!-- spring使用listener初始化bean(service和dao层bean) -->
        <!-- <listener>
              <listener-class>
                  org.springframework.web.context.ContextLoaderListener
              </listener-class>
        </listener> -->
    
        <!-- spring使用servlet初始化bean(controller层bean) -->
        <servlet>
            <servlet-name>DispatcherServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!-- init-param指定DispatcherServlet上下文配置文件的位置,为局部配置文件,只对DispatcherServlet有用
                 如果没有配置init-param,会默认读取/WEB-INF/${servlet-name}-servlet.xml -->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springConfig/spring-all.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>DispatcherServlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
        
      <display-name>Archetype Created Web Application</display-name>
    </web-app> 

    -------------------------------------------------以下内容摘自https://blog.csdn.net/kang389110772/article/details/50758994----------------------------------

    一个标准的Spring Web项目("Spring MVC Project"模板或者Roo创建的)会在web.xml中包含`ContextLoaderListener`和`DispathcerServlet`.**为什么有些可以只引用`DispatcherServlet`就可以加载所有的配置?**  
    我知道 ContextLoaderListener 是应该用在加载与web无关的bean, DispatcherServlet用来加载web相关的bean(Controller相关的等等)。这样就会导致两个 Context:一个父级的和一个孩子级的

    背景:  
    我一直按照标准的做法做了很多年。  
    这经常引起两个context之间的依赖关系问题。在过去我总是可以找个对应的解决办法,并且我很强烈觉得这个机制可以使软件架构更好。但是我现在面临一个问题[problem with the events of the both >contexts](http://stackoverflow.com/questions/8534222/how-to-bridge-spring-application-context-events-to->an-other-context). 

    然而这个问题也让我重新思考两个context的模式,我自己问自己:为什么我要把自己带到这个麻烦之中,为什么不把Spring所有的配置放在一个DispatcherServlet文件并且移除掉ContextLoaderListener。(我也会有不同的配置文件,但是只有一个context)。  
    有什么理由可以支持移除`ContextLoaderListener`吗?

    在你这种情况下,没有理由再去使用ContextLoaderListener和applicationContext.xml配置文件。如果你的app只使用DispatcherServlet就能很好的工作,那么就应该坚持只用这个,这个简单。  
    是的,一般推荐的方式是把web不相关的东西放到 webapp级别的 context,但是这除了让有点不方便什么都没有。  
    需要强烈使用webapp的理由如下:  
    * 如果你有多个需要共享服务的DispatcherServlet
    * 如果你有逻辑关系需要访问Spring内部的service
    * 如果你有需要hook 在webapp级别的context的Servlet filters

    如果上述情形都不适合你,那么你完全不必增加复杂度。  
    有一点需要关注的是,当增加后台任务到servlet的context时,比如调度任务、JMS连接等等,如果你忘了添加<load-on-startup>,这些任务将不会第一个起来。

    个人理解,如有错误,欢迎指正!
  • 相关阅读:
    [loj3364]植物比较
    [loj3366]嘉年华奖券
    [atARC105F]Lights Out on Connected Graph
    [atARC105D]Let's Play Nim
    [atARC058F]Lroha Loves Strings
    [loj3347]有趣的旅途
    [atAGC001F]Wide Swap
    [cf1392I]Kevin and Grid
    [loj3340]命运
    [loj3046]语言
  • 原文地址:https://www.cnblogs.com/gllegolas/p/11657558.html
Copyright © 2011-2022 走看看