ServiceA.java文件:
查看Spring Tx的相關日志: 可以看到只創建了一個事物ServiceA.service方法的事務,但是callSelf方法卻沒有被事務增強;
分析原因:Spring事務生成的對象也是被Cglib或JDK代理的對象,就區別於該對象本身了,
代理的對象執行方法之前會走攔截器鏈,就不能同this方法.
解決方案:
- 使用Autowired注解將自身注入,然后調用注入屬性的方法;
驗證輸出結果: 確實初始化了callSelf的事務;
2.之前Aop可以將代理對象暴露到當前線程局部變量中;
<aop:aspectj-autoproxy expose-proxy="true"/>
通過嘗試發現,SpringTx也可以使用該配置,將創建的對象加入到當前線程局部變量;
也許覺得SpringAop和SpringTx不一樣啊,但其實兩者都實現了AbstractAutoProxyCreator類,同樣設置expose-proxy也能生效,綁定到線程局部變量上;
調用方式如下:
驗證輸出結果:可以看到確實 callSelf方法也被Spring事務增強到了.
3.按照道理來說tx:annotation-driven標簽應該也有expose-proxy屬性,但是很不幸:
<tx:annotation-driven>標簽確實不允許expose-proxy屬性設置,有proxy-target-class屬性;
查看AopNamespaceUtils的useClassProxyingIfNecessary方法:
Line 91-94行是用來解析標簽時候定義expose-proxy、proxy-target-class兩個屬性,Aop以及Tx都會調用這個方法, 問題就是這里了, <aop:aspectj-autoproxy>標簽約束里有expose-proxy,
那可以解析,但是<tx:annotation-driven>標簽沒有expose-proxy我解析啥子呢,
改動下解析Tx標簽時,將expose-proxy設置為true; (此處涉及到改動源代碼,jar包是無法直接修改的,我修改的Spring的源碼,如果需要導入Spring的jar包 然后在修改之后導出成jar包)
驗證下輸出結果: 可以看到也實現了調用自身方法, 其實和方法二應該是一個意思;