最近作一個項目,項目的框架採用是Spring3MVC+MyBatis3.1。但是在開發過程當中發現配置的事務無論用。 web
出現這個問題的現象是用Junit調試事務管用,而部署到Tomcat中就無論用了。先看看事務的配置: spring
<!--proxy-target-class="true"強制使用cglib代理 若是爲false則spring會自動選擇-->
<aop:aspectj-autoproxy proxy-target-class="true"/> express
<!-- Transaction manager for a single JDBC DataSource -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut expression="execution(public * com.luyou.platform.service.impl.*Impl.*(..))" id="pointcut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
</aop:config>
mvc
採用如下兩種方法調試: app
1、Debug視圖 框架
一、Junit下的 spa
發現配置事務的AOP已經包進來了。再看看Tomcat中運行的Debug截圖: 代理
顯然AOP沒有被包進來。 調試
2、Log4J的記錄: orm
Junit下的記錄:
Spring託管了事務。
Tomcat運行時的記錄:
Spring沒有託管事務。
從以上兩種方法的調試說明了,事務的配置是正確的,只是在部署到Tomcat中,沒有被託管。爲何會在Junit的時候就能夠呢?得看看Junit的配置:
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class})
@ContextConfiguration("classpath:applicationContext.xml")
這是Junit加載Spring容器的註解。ContextConfiguration會把applicationContext.xml的Bean都加載了,這就說明Tomcat在運行時沒有將applicationContext.xml的Bean加載進來。問了前輩,前輩的回話是這樣的:
切面配置在了root applicationContext的bean上了,而spring mvc會根據xxx-servelt.xml生成一個本身的applicationContext,他的父applicationContext爲root applicatonContext,當mvc有本身的bean時便再也不去向父context要bean,致使聲明事務無效。
看了前輩的這個郵件,我將applicationContext.xml中配置事務的AOP複製到XXX-servlet.xml中。再調試,Tomcat中運行項目事務被Spring託管了,也就是問題解決了!!
問題解決後查看了Spring3.1的Docs發現瞭如下的內容:
These inherited beans can be overridden in the servlet-specific scope, and you can define new scope-specific beans local to a given Servlet instance.
Context hierarchy in Spring Web MVC Upon initialization of a DispatcherServlet, Spring MVC looks for a file named [servlet-name]-servlet.xml in the WEB-INF directory of your web application and creates the beans defined there, overriding the definitions of any beans defined with the same name in the global scope.