1. 程式人生 > >spring 事物 關於在同一個類中一個方法呼叫另一個方法,事物的傳播行為會失效

spring 事物 關於在同一個類中一個方法呼叫另一個方法,事物的傳播行為會失效

spring 提供了強大的事物管理機制,直接到在方法或者類上加@Transactional,也可以使用XML配置事物。

在一次的測試中發現當一個方法在同一個類被其它方法呼叫的時候,導致事物的傳播行為不生效。

具體說明:

類結構:

public class Demo {

	public void methodA() {
		this.methodB();
	}
	
	
	public void methodB() {
		
	}
	
}

1、如果在methodA中加入:@Transactional,mehodB不加@Transactional,那麼呼叫methodA,methodA的事物會生效,因為methodA預設的propagation為PROPAGATION_REQUIRED,此時methodB會加入到methodA中

2、如果methodA與methodB都加上@Transactional,那麼呼叫methodA,methodA的事物會生效,此時和 1 中情況一樣,事物會生效,也是由於methodB的事物會加入到methodA中,但是,其實methodA中通過this.methodB()的呼叫是沒有觸發spring 的事物,原因會統一講解。

3、如果methodA配置@Transactional,methodB配置@Transactional( propagation = Propagation.REQUIRES_NEW ),那麼呼叫methodA,如果methodA出現異常,根據spring的事物傳播行為,其實methodB應該是入庫才對,但是我測試發現根本沒有生效,一樣是全部回滾。

原因解釋:

spring的事物管理通過AOP代理來實現, 根據aop的思想,不可能在具體類Demo上直接處理事物,而是通過代理類來處理,代理類在呼叫具體類的方法來實現,根據上面的情景methodA通過this呼叫methodB,那麼此時相當於呼叫methodB時是沒有經過代理類的呼叫,因此spring無法對事物的傳播行為做處理。

下面CGLIB生成的代理物件反編譯的類檔案:


其實JDK代理,也是類似的原理,不同的是,JDK代理是通過實現介面來重新生成代理物件,通過反射呼叫被代理類的方法