1、PROPAGATION_REQUIRED:如果當前沒有事務,就創建一個新事務,如果當前存在事務,就加入該事務,該設置是最常用的設置。
2、PROPAGATION_SUPPORTS:支持當前事務,如果當前存在事務,就加入該事務,如果當前不存在事務,就以非事務執行。‘
3、PROPAGATION_MANDATORY:支持當前事務,如果當前存在事務,就加入該事務,如果當前不存在事務,就拋出異常。
4、PROPAGATION_REQUIRES_NEW:創建新事務,無論當前存不存在事務,都創建新事務。
5、PROPAGATION_NOT_SUPPORTED:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
6、PROPAGATION_NEVER:以非事務方式執行,如果當前存在事務,則拋出異常。
7、PROPAGATION_NESTED:如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則執行與PROPAGATION_REQUIRED類似的操作。
羅列了7種spring的事務傳播行為,我們具體來看看它的實現。在這里,我們使用spring annotation注解實現事務。
實現事務的類BusinessServiceImpl
package com.aop; import org.springframework.aop.support.AopUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.entity.Student; @Service("businessSerivce") public class BusinessServiceImpl implements IBaseService { @Autowired IStudentDao studentDao; @Autowired IBaseServiceB baseServiceb; @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackFor = Exception.class) public String doA() throws Exception { Student st = new Student(); st.setId(1); st.setSex("girl"); st.setUsername("zx"); studentDao.insertStudent(st); System.out.println(baseServiceb); System.out.println("是否是代理調用,AopUtils.isAopProxy(baseServiceb) : " + AopUtils.isAopProxy(baseServiceb)); System.out .println("是否是cglib類代理調用,AopUtils.isCglibProxy(baseServiceb) : " + AopUtils.isCglibProxy(baseServiceb)); System.out.println("是否是jdk動態接口代理調用,AopUtils.isJdkDynamicProxy(baseServiceb) : " + AopUtils.isJdkDynamicProxy(baseServiceb)); //使用代理調用方法doB() baseServiceb.doB(); int i = 1 / 0;// 拋出異常,doB()的事務事務回滾 return "success"; } // @Transactional(propagation = Propagation.REQUIRES_NEW, isolation = // Isolation.DEFAULT, rollbackFor = Exception.class) // public String doB() throws Exception { // Student st = new Student(); // st.setId(2); // st.setSex("girl"); // st.setUsername("zx2"); // studentDao.insertStudent(st); // // return "success"; // } }
實現事務的類BusinessServiceImpl
package com.aop; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.entity.Student; @Service("businessSerivceB") public class BusinessServiceImplB implements IBaseServiceB { @Autowired IStudentDao studentDao; @Transactional(propagation = Propagation.REQUIRES_NEW,isolation=Isolation.DEFAULT,rollbackFor=Exception.class) public String doB() throws Exception { Student st = new Student(); st.setId(2); st.setSex("girl"); st.setUsername("zx2"); studentDao.insertStudent(st); return "success"; } }
測試類:
package com.aop; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.thread.service.IBaseFacadeService; //@RunWith(SpringJUnit4ClassRunner.class) //@ContextConfiguration(locations = { "classpath:/spring-ibatis.xml", "classpath:/spring-jdbctemplate.xml" }) public class TestStudentDao { public static void main(String[] args) { try { BeanFactory factory = new ClassPathXmlApplicationContext("spring-jdbctemplate.xml"); IBaseService service = (IBaseService) factory.getBean("businessSerivce"); service.doA(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
測試結果:
om.aop.BusinessServiceImplB@14b75fd9
是否是代理調用,AopUtils.isAopProxy(baseServiceb) : true
是否是cglib類代理調用,AopUtils.isCglibProxy(baseServiceb) : true
是否是jdk動態接口代理調用,AopUtils.isJdkDynamicProxy(baseServiceb) : false
java.lang.ArithmeticException: / by zero

從測試結果可以看到,我們在數據庫中成功插入了doB()方法中要插入的數據,而doA()中插入的數據被回滾了,這是因為我們在doB()方法中加入ROPAGATION_REQUIRES_NEW傳播行為,doB()創建了屬於自己的事務,掛起了doA()中的事務,所以事務B提交了,而事務A因為執行異常插入的數據被回滾了。
如果我們將BusinessServiceImplB做下修改,改為第一種傳播行為ROPAGATION_REQUIRED
package com.aop; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.entity.Student; @Service("businessSerivceB") public class BusinessServiceImplB implements IBaseServiceB { @Autowired IStudentDao studentDao; @Transactional(propagation = Propagation.REQUIRED,isolation=Isolation.DEFAULT,rollbackFor=Exception.class) public String doB() throws Exception { Student st = new Student(); st.setId(2); st.setSex("girl"); st.setUsername("zx2"); studentDao.insertStudent(st); return "success"; } }
測試結果:
com.aop.BusinessServiceImplB@97c87a4
是否是代理調用,AopUtils.isAopProxy(baseServiceb) : true
是否是cglib類代理調用,AopUtils.isCglibProxy(baseServiceb) : true
是否是jdk動態接口代理調用,AopUtils.isJdkDynamicProxy(baseServiceb) : false
java.lang.ArithmeticException: / by zero

從結果可以看到,我們沒有成功插入數據,這是為什么呢?因為我們使用的是第一種傳播行為PROPAGATION_REQUIRED ,doB()方法被加入到doA()的事務中,doA()執行時拋出了異常,因為doB()和doA()同屬於一個事務,則執行操作被一起回滾了。其實在doB()中我們不加入注解,也等同PROPAGATION_REQUIRED的效果。
接下來我們再來看看第五種傳播行為PROPAGATION_NOT_SUPPORTED,我們同樣修改B類,如下
package com.aop; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.entity.Student; @Service("businessSerivceB") public class BusinessServiceImplB implements IBaseServiceB { @Autowired IStudentDao studentDao; @Transactional(propagation = Propagation.NOT_SUPPORTED,isolation=Isolation.DEFAULT,rollbackFor=Exception.class) public String doB() throws Exception { Student st = new Student(); st.setId(2); st.setSex("girl"); st.setUsername("zx2"); studentDao.insertStudent(st); return "success"; } }
測試結果:

可以看到doB()方法成功插入了數據。doA()方法中插入的數據被回滾了。這是因為傳播行為PROPAGATION_NOT_SUPPORTED是doB()以非事務執行的,並且提交了。所以當doA()的事務被回滾時,doB()的操作沒有被回滾。
其他的傳播行為就不一一列舉了,機制是差不多的。
注意:在上面的實例中,我沒有把doB()方法放在類BusinessServiceImpl,而是放在BusinessServiceImplB中,這是因為spring通過掃描所有含有注解的@Trasation的方法,使用aop形成事務增強advise。但是加入增強時是通過代理對象調用方法的形式加入的,如果將doB()方法放在doA()方法直接調用時,在調用doB()方法的時候是通過當前對象來調用doB()方法的,而不是通過代理來調用的doB()方法,這個時候doB()方法上加的事務注解就失效了不起作用。在Spring事務傳播行為在內部方法不起作用講到。
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:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc" 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-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-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/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd" default-lazy-init="false"> <context:component-scan base-package="com.aop"/> <aop:aspectj-autoproxy proxy-target-class="true"/> <!-- 數據 --> <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/lpWeb"/> <property name="username" value="root"/> <property name="password" value="root123"/> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name = "dataSource" ref="dataSource"/> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> </beans>
