javascript
Spring中事务内部调用引发的惨案
在一個類內部有2個方法foo和bar,其中bar方法配有注解(@Transactional),即bar是事務執行的,而foo不是事務執行,當foo方法內部調用bar方法后,bar方法的事務是不生效的。示例代碼如下:
public?class?ServiceTest?{public?void?foo(){this.bar();//調用自身的方法;}@Transactionalpublic?void?bar(){System.out.println("this?is?bar");//數據庫操作} }原因如下:
????Spring中通過注解來完成事務的功能,實際是通過SpringAOP來實現的,而SpringAOP中,使用this來調用自身的方法時,此對象引用上的方法直接會被調用,不會調用代理的方法(SpringAOP原理是產生代理類)。因此bar方法的事務不會生效。如果直接調用bar方法,此時事務是生效的。
????解決方法有:
????一、將bar方法放在另一個service類中。這種方法簡單,但是造成代碼的冗余。
????二、可以將注解@Transactional放在foo方法上。這種方法造成的影響:加入foo方法的一些操作是不需要事務的,這會延長事務執行的時間。
????三、在foo方法中不要直接使用this來調用bar方法,通過調用代理類的bar方法。
public?void?foo(){if(null?!=?AopContext.currentProxy()){??((ServiceTest)AopContext.currentProxy()).bar();??}else{??bar();??}??????}????我們顯示的調用了AopContext來獲取當前代理對象,然后調用其方法,這樣做還必須的一個步驟是將當前的代理暴露給線程使用,在配置文件中需要配置一個參數:
<property?name="exposeProxy">??<value>true</value>??</property>?
或者在application-context.xml文件中添加配置:
<aop:aspectj-autoproxy?proxy-target-class="true"?expose-proxy="true"/>?
它是ProxyConfig的一個參數,默認是false,如果不設置這個參數,那么上述java代碼將無法獲取當前線程中的代理對象。
這種方法可以成功觸發攔截,但是也帶來了其他問題,比如代碼的織入,我們的代碼將變得復雜而且晦澀,而且嚴格要求系統針對于當前的bean必須配置攔截器,否則會因為找不到攔截器而拋出異常。
from:?https://my.oschina.net/hnrpf/blog/659673?
總結
以上是生活随笔為你收集整理的Spring中事务内部调用引发的惨案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JavaScript 函数定义方式
- 下一篇: Spring事务处理时自我调用的解决方案