spring中expose-proxy的作用與原理


 

 

 也就是說我們首先調用的是AOP代理對象而不是目標對象,首先執行事務切面,事務切面內部通過TransactionInterceptor環繞增強進行事務的增強,即進入目標方法之前開啟事務,退出目標方法時提交/回滾事務

 

1、測試代碼如下:

 

 1 public interface AService {  
 2     public void a();  
 3     public void b();  
 4 }  
 5    
 6 @Service()  
 7 public class AServiceImpl1 implements AService{  
 8     @Transactional(propagation = Propagation.REQUIRED)  
 9     public void a() {  
10         this.b();  
11     }  
12     @Transactional(propagation = Propagation.REQUIRES_NEW)  
13     public void b() {  
14     }  
15 }  

 

2、問題:

目標對象內部的自我調用將無法實施切面中的增強,如圖所示

 

 

 此處的this指向目標對象,因此調用this.b()將不會執行b事務切面,即不會執行事務增強,因此b方法的事務定義“@Transactional(propagation = Propagation.REQUIRES_NEW)”將不會實施,即結果是b和a方法的事務定義是一樣的(我們可以看到事務切面只對a方法進行了事務增強,沒有對b方法進行增強)


Q1:b中的事務會不會生效?
A1:不會,a的事務會生效,b中不會有事務,因為a中調用b屬於內部調用,沒有通過代理,所以不會有事務產生。
Q2:如果想要b中有事務存在,要如何做?
A2:<aop:aspectj-autoproxy expose-proxy=“true”> ,設置expose-proxy屬性為true,將代理暴露出來,使用AopContext.currentProxy()獲取當前代理,將this.b()改為((UserService)AopContext.currentProxy()).b()

3、解決方案

此處a方法中調用b方法時,只要通過AOP代理調用b方法即可走事務切面,即可以進行事務增強,如下所示:

Java代碼  
1 public void a() {  
2   aopProxy.b();//即調用AOP代理對象的b方法即可執行事務切面進行事務增強  
3 } 

判斷一個Bean是否是AOP代理對象可以使用如下三種方法:

AopUtils.isAopProxy(bean)        : 是否是代理對象;

AopUtils.isCglibProxy(bean)       : 是否是CGLIB方式的代理對象;

AopUtils.isJdkDynamicProxy(bean) : 是否是JDK動態代理方式的代理對象;

4、通過ThreadLocal暴露Aop代理對象

1、開啟暴露Aop代理到ThreadLocal支持(如下配置方式從spring3開始支持)

1 Java代碼  
2 <aop:aspectj-autoproxy expose-proxy="true"/><!—注解風格支持-->  
3 Java代碼  
4 <aop:config expose-proxy="true"><!—xml風格支持--> 

 

2、修改我們的業務實現類

this.b();-----------修改為--------->((AService) AopContext.currentProxy()).b();


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM