spring註解與springMVC註解掃描的問題

  在將spring與springMVC結合使用時,當咱們使用註解的時候,通常都是在spring配置文件中配置註解掃描dao層、service層的包,在springMVC配置文件中配置註解掃描controller,本身在練習spring+SpringMVC+mybatis的項目時對這種作法只知其一;不知其二,因此在練習項目的時候在實踐中對本身的一些想法進行了驗證。web

  • 通常的配置
    •   spring配置文件中
      <?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:aop="http://www.springframework.org/schema/aop"
              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-2.5.xsd
                  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
                  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
                    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
                  
           <!-- 啓用註解  -->
          <context:annotation-config />
      
          <!-- 設置使用註解的類所在的包 -->
          <context:component-scan base-package="dao,service.*"></context:component-scan>
          
          <bean id="propertyConfigurer"
              class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
              <property name="locations">
                  <list>
                      <value>classpath:config/jdbc.properties</value>
                  </list>
              </property>
          </bean>
          <!-- c3p0鏈接池配置 -->  
           <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">  
                 <!-- 四大參數的name不能換,和鏈接池的構造函數有關-->
                <property name="driverClass" value="${jdbc.driverClassName}"/>
                <property name="jdbcUrl" value="${jdbc.url}" />
                <property name="user" value="${jdbc.username}" />
                <property name="password" value="${jdbc.password}" />  
        
                 <!--鏈接池中保留的最大鏈接數。默認值: 15 -->   
                <property name="maxPoolSize" value="20"/>  
                <!-- 鏈接池中保留的最小鏈接數,默認爲:3-->  
                <property name="minPoolSize" value="2"/>  
                <!-- 初始化鏈接池中的鏈接數,取值應在minPoolSize與maxPoolSize之間,默認爲3-->  
                <property name="initialPoolSize" value="2"/>  
        
                <!--最大空閒時間,60秒內未使用則鏈接被丟棄。若爲0則永不丟棄。默認值: 0 -->   
                <property name="maxIdleTime" value="60"/>  
                  
                <!-- 當鏈接池鏈接耗盡時,客戶端調用getConnection()後等待獲取新鏈接的時間,超時後將拋出SQLException,如設爲0則無限期等待。單位毫秒。默認: 0 -->   
                <property name="checkoutTimeout" value="3000"/>  
                  
                <!--當鏈接池中的鏈接耗盡的時候c3p0一次同時獲取的鏈接數。默認值: 3 -->   
                <property name="acquireIncrement" value="2"/>  
        
               <!--定義在從數據庫獲取新鏈接失敗後重復嘗試的次數。默認值: 30 ;小於等於0表示無限次-->   
                <property name="acquireRetryAttempts" value="0"/>  
        
                <!--從新嘗試的時間間隔,默認爲:1000毫秒-->   
                <property name="acquireRetryDelay" value="1000" />  
        
                <!--關閉鏈接時,是否提交未提交的事務,默認爲false,即關閉鏈接,回滾未提交的事務 -->   
                <property name="autoCommitOnClose" value="false"/>  
         
                <!--c3p0全局的PreparedStatements緩存的大小。若是maxStatements與maxStatementsPerConnection均爲0,則緩存不生效,只要有一個不爲0,則語句的緩存就能生效。若是默認值: 0-->   
                <property name="maxStatements" value="100"/>  
                <!--maxStatementsPerConnection定義了鏈接池內單個鏈接所擁有的最大緩存statements數。默認值: 0 -->   
                <property name="maxStatementsPerConnection" value="0"/>  
           </bean>
           <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
            <!-- 配置mybatis配置文件 -->
            <property name="configLocation">
               <value>classpath:config/sqlMapConfig.xml</value>
            </property>
             <!-- 實體類映射文件路徑,能夠在這裏直接配置,也能夠在configLocation配置的文件中配置 ibatis2不支持 -->  
             <!-- <property name="mapperLocations" value="classpath:config/sqlmap/*.xml" />  -->
          </bean>
          <!-- Dao -->
          <bean id="ibatisDao" class="dao.IbatisDao">
               <property name="dataSource" ref="dataSource"></property> 
               <!-- 這裏的dao繼承SqlMapClientDaoSupport,因此要顯示的配置注入 sqlMapClient-->
                <property name="sqlMapClient">
                  <ref bean="sqlMapClient"/>  
               </property>   
          </bean>
          <!-- 開啓事務註解 -->
          <tx:annotation-driven transaction-manager="transactionManager"/>
          <!-- 定義事務管理器(聲明式的事務) -->  
          <bean id="transactionManager"
              class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
              <property name="dataSource" ref="dataSource" />
          </bean>
          
      </beans>

      這裏咱們配置了事務管理器和基本的dao。service層採用的是註解注入ajax

    •  springMVC配置文件中:
      <?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:p="http://www.springframework.org/schema/p"     
              xmlns:context="http://www.springframework.org/schema/context"     
         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   
             http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd   
             http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd   
             http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
      
      <!--     啓用spring mvc 註解 -->
          <context:annotation-config />
      
          <!-- 設置使用註解的類所在的包 -->
         <context:component-scan base-package="controller"></context:component-scan>   
           
          <!-- 完成請求和註解POJO的映射  3.1後已通過時 與DefaultAnnotationHandlerMapping配套使用
          <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />-->
          <!-- 新的註解映射-->
          <!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> -->
          
          
           <!-- 使用新的註解映射必須指定 RequestMappingHandlerMapping去替代過期的DefaultAnnotationHandlerMapping-->
           <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
           <!-- 使用ajax向前臺返回json須要在註解映射中添加轉換器 -->
           <!-- 依賴包爲jackson-core 、 jackson-annotation、 jackson-databind -->
           <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
                    <property name="messageConverters">
                        <list>
                            <ref bean="jsonHttpMessageConverter"/>
                        </list>
                    </property>
          </bean>
      <bean id="jsonHttpMessageConverter" 
          class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" /><!--   用於jackson2 -->
           <!--  class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/> -->
          
          <!-- 對轉向頁面的路徑解析。prefix:前綴, suffix:後綴 -->
          <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/page/" p:suffix=".jsp" />
      </beans>

      springMVC配置文件中配置了指定的HandlerAdapter和HandlerMapping以及Resolver。
      在這種配置下,項目能正常運行,配置了@Transactional的service中的事務也能被咱們的事務管理器管理。spring

  • 只在spring配置文件中啓用註解掃描(關閉springmvc掃描),掃描dao、service、controller。
      這種狀況下,項目啓動正常,可是沒法處理咱們的請求,鑑於springmvc容器是spring容器的子容器,我猜測因爲controller中的全部請求處理方法我都是採用@requestMapping來進行配置的,requestMapping都是由咱們的springMVC配置文件中配置的HandlerAdapter和HandlerMapping以及Resolver的Bean來進行處理(即便咱們不在這裏面配置,spingmvc也有默認的),可是父容器又不能訪問子容器的bean,因此即便掃描了controller包也沒法將controller的處理方法與咱們的請求正確mapping,因此這裏若是僅僅在spring中掃描全部包,項目是沒法實現正常運轉的。
  • 只在spring配置文件中啓用註解掃描,掃描dao、service、controller,而且在spring配置文件中配置springmvc的HandlerAdapter和HandlerMapping以及Resolver。
      這種狀況項目與咱們通常配置的效果同樣,這種狀況就至關於咱們在spring中也完成了spingmvc的配置,將本來應該在springmvc容器中的bean直接在spring中配置,雖然效果是同樣的,可是不建議這種作。這種配置的結果也表明咱們上一種狀況出現的緣由的猜測是對的,spring父容器沒法訪問springmvc中的bean,沒法將掃描到的controller與請求url正確適配。
  • 在springMVC配置文件中啓用註解掃描(關閉spring掃描),掃描dao、service、controller。
      這種狀況下項目能正常跳轉,可是咱們經過@Transactional配置的service事務失效,這裏是由於spring容器配置了事務管理器後,裝配的service都是通過cglib代理過的實例,具備事務功能,而springmvc容器裝配的service是沒有進行代理處理的,因此是沒有事務功能的,這一點能夠參見這篇博客http://blog.csdn.net/haoyifen/article/details/51172647。這裏我試着在springMVC配置文件中也配置了一個事務管理器事後,發現一切正常了,由springmvc裝配的service一樣也具有事務功能,這裏就很奇怪,爲何父容器配置的事務管理器子容器沒法使用呢?父容器中的bean子容器都是能夠訪問的,爲何沒有使用呢?到這裏差很少能夠回答開始的問題了,爲何要在spring中掃描dao、service,由於經過spring容器掃描dao以及service能夠進行事務的加強,若是你僅僅在一個子容器中進行事務的加強那麼其餘的serviceBean是不會被事務加強的(好比第四種狀況中,若是咱們在spring容器中手動配置一個bean,那麼這個bean不是由springmvc裝配的,而咱們的事務管理器在springmvc中,這個bean就不具有事務的功能)。而controller之因此要在springmvc中配置,由於spring容器沒法訪問到springmvc容器的bean(HandlerAdapter和HandlerMapping以及Resolver等),沒法完成請求與hander的正確適配,若是要強行實現,在spring中配置HandlerAdapter和HandlerMapping以及Resolver則顯得太過牽強。在書上看到的一種說法是這樣也體現了分層的概念,dao、service等web層都須要使用的bean應該直接在spring容器中裝配,而controller這種則放在專門處理請求跳轉的springmvc容器中,相對於將全部bean配置在spring容器中,也體現了權限控制的思想吧。
相關文章
相關標籤/搜索