菜鸟学Spring之——父子容器的概念

Spring父子容器

我们之前将所有的容器创建过程都放在了一个配置文件中(一个配置文件中整合了SpringMVC、Mybatis等等)这样做太凌乱了。如果有一个过程出错了,整个容器都会出错,这时就引入了父子容器,在启动的时候先启动除了Controller以外的所有的其他的类型对象,而在真正Servlet启动的时候只把Controller和Intercepter加载出来就行了。(所有的Handle都是Spring体系下的东西)

Controller层属于Spring体系,Service层属于SpringMVC体系

@Service,@Repository,@Autowired这些注解在没有SpringMVC的体系下都可以单独存在,这种可以单独存在的如果和SpringMVC配置在一个配置文件中就比较凌乱了。SpringMVC应该有他自己的容器,Spring有他自己的容器。Spring用来管理Mybatis,SpringMVC。

真正启动一个SpringMVC项目的时候第一件事应该是启动一个Listener(监听器,只负责监听,不干遇项目的执行)。这Listener监听全局事务,当某个事务发生时会触发他的回调。Servlet是当某个请求发生时会触发他的回调。Filter是当一个请求过来时,他会在Servlet之前触发回调,并且决定Servlet是否执行

Listener的配置



<web-app>
  <display-name>Archetype Created Web Applicationdisplay-name>

  <context-param>
    <param-name>contextConfigLocationparam-name>
    <param-value>classpath:applicationContext.xmlparam-value>
  context-param>

  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
  listener>


  <servlet>
    <servlet-name>springservlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
    <init-param>
      <param-name>contextConfigLocationparam-name>
      <param-value>classpath:spring-*.xmlparam-value>
    init-param>
  servlet>

  <servlet-mapping>
    <servlet-name>springservlet-name>
    <url-pattern>/url-pattern>
  servlet-mapping>

web-app>

这时项目的启动顺序变为:先启动applicationContext容器,然后再启动spirng-mvc容器(原来是一口大锅,现在是鸳鸯锅了)

接下来把我们之前创建的那一口大锅整理一下。

原来的模样


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <context:component-scan base-package="com.lanou">context:component-scan>
    
    <mvc:annotation-driven>mvc:annotation-driven>
    <mvc:resources mapping="/static/**" location="/static/">mvc:resources>


    
    <bean id="dataSource" class="org.apache.ibatis.datasource.pooled.PooledDataSource">
        <property name="driver" value="com.mysql.cj.jdbc.Driver">property>
        <property name="url" value="jdbc:mysql://localhost:3306/db_zbmanager?serverTimezone">property>
        <property name="username" value="root">property>
        <property name="password" value="zaq991221">property>
    bean>


    
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource">property>
        <property name="mapperLocations" value="classpath:mapper/*.xml">property>
    bean>

    <bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.lanou.mapper">property>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory">property>
    bean>

    
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource">property>
    bean>





    
    <tx:annotation-driven transaction-manager="transactionManager">tx:annotation-driven>






beans>

整理后的模样

applicationContext.xml


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       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/tx
           http://www.springframework.org/schema/tx/spring-tx.xsd

">

    

    <context:component-scan base-package="com.lanou">
        
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Component"/>
        <context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.RestController"/>
    context:component-scan>

    
    <bean id="dataSource" class="org.apache.ibatis.datasource.pooled.PooledDataSource">
        <property name="driver" value="com.mysql.cj.jdbc.Driver">property>
        <property name="url" value="jdbc:mysql://localhost:3306/db_zbmanager?serverTimezone">property>
        <property name="username" value="root">property>
        <property name="password" value="zaq991221">property>
    bean>


    
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource">property>
        <property name="mapperLocations" value="classpath:mapper/*.xml">property>
    bean>

    <bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.lanou.mapper">property>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory">property>
    bean>

    
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource">property>
    bean>


    


    
    <tx:annotation-driven transaction-manager="transactionManager">tx:annotation-driven>


beans>

spring-mvc.xml


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/aop
           https://www.springframework.org/schema/aop/spring-aop.xsd
           http://www.springframework.org/schema/mvc
           https://www.springframework.org/schema/mvc/spring-mvc.xsd
">

    <context:component-scan base-package="com.lanou.controller">context:component-scan>

    <mvc:annotation-driven>mvc:annotation-driven>
    <mvc:resources mapping="/static/**" location="/static/">mvc:resources>

beans>

这样项目启动的时候就会将大部分类的创建扔到了父容器中,而子容器还没有启动。当一个访问来子容器才启动,子容器的Controller才创建出来(只需要创建Controller就行了,别的东西就不会再创建了)

这样容器启动的过程会变慢一点,但是运行速度会变快。

这里需要注意一下,如果子容器扫描一个包,父容器也扫描相同的包,或者子容器创建一套数据库链接,父容器也创建一套数据库链接。这样会出大问题,父容器的事务链接过程会被子容器覆盖,同时覆盖掉原来在父容器中声明好的可以使用的事务管理过程,这时候事务就不会生效了。所以不要把在父容器中声明过的对象在子容器中在声明一遍,父子容器一定要把活分清。子容器就启动SpringMVC体系需要的东西,父容器加载为子容器服务的所有组件。

日志系统应该放在父容器中,但是刚才我们整理的父容器放的都是和数据库有关的东西,我不想把日志系统加进去,怎么办?稍微改一下之前的配置

web.xml

 <context-param>
    <param-name>contextConfigLocationparam-name>
    <param-value>classpath:applicationContext*.xmlparam-value>
  context-param>

  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
  listener>

创建一个applicationContext*.xml文件,将日志系统和AOP过程放到这里。

菜鸟学Spring之——父子容器的概念_第1张图片

注意:这里的applicationContext.xml和applicationContext-log.xml是一个容器,他们和spring-mvc之间是两个容器。(listener启动了父容器,servlet启动了子容器)

你可能感兴趣的:(Java框架)