Spring AOP無法呼叫自身方法的原因
1、問題概述
在使用Spring AOP時,或多或少會碰到一些方法無法被增強的問題,有時同一個類裡面的方法有的可以被增強,有的卻無法被增強。要分析原因,首先要從Spring AOP的實現機制入手。
Aop底層實現有兩種方法:
1、基於JDK動態代理,通過介面來實現方法攔截,所以必須要確保要攔截的目標方法在介面中有定義,否則將無法實現攔截
2、GCLib動態代理,通過動態生成子類來實現方法攔截,必須確保要攔截的目標方法可被子類訪問,即目標方法必須定義為非final。且非私有例項方法。
2、例子
服務員業務類,代理目標類
public class Waiter {
public void greetTo(String name) {
System.out.println("Waiter Greet to " + name);
}
public void serverTo(String name) {
System.out.println("Waiter Server to " + name);
}
}
前置增強類
public class GreetBeforeAdivce implements MethodBeforeAdvice {
public void before(Method method, Object[] objects, Object o) throws Throwable {
// 輸出切點
String clientName = (String) objects[0];
System.out.println("How are you " + clientName + " ?(切點方法為:" + method + ")");
}
}
beans-aware.xml配置
<bean id="waiter" class="demo04.advisor.Waiter" />
<bean id="greetBeforeAdviceAdvice" class="demo04.advisor.GreetBeforeAdivce" />
<!--通過Advisor自動建立代理-->
<bean id="regexpAdvisor"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"
p:patterns=".*To.*" p:advice-ref="greetBeforeAdviceAdvice" />
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" p:proxyTargetClass="true" />
測試類
public class AopAwareTest {
@Test
public void autoProxy(){
String config="com/smart/autoproxy/beans-aware.xml";
ApplicationContext ctx=new ClassPathXmlApplicationContext(config);
Waiter waiter=(Waiter)ctx.getBean("waiter");
waiter.greetTo("John");
waiter.serveTo("John");
}
}
輸出(可以看到兩個方法都被織入了增強,增強被正確地織入匹配的連線點中)
How are you John ?(切點方法為:public void demo04.advisor.Waiter.serverTo(java.lang.String))
Waiter Server to John
How are you John ?(切點方法為:public void demo04.advisor.Waiter.greetTo(java.lang.String))
Waiter Greet to John
現在將Waiter中的serverTo()方法改造一下,讓serverTo呼叫greetTo方法,如下:
public class Waiter {
public void greetTo(String name) {
System.out.println("Waiter Greet to " + name);
serverTo(name);//這裡呼叫自身的severTo方法
}
public void serverTo(String name) {
System.out.println("Waiter Server to " + name);
}
}
再次執行測試類,輸出為:
How are you John ?(切點方法為:public void demo04.advisor.Waiter.greetTo(java.lang.String))
Waiter Greet to John
Waiter Server to John
How are you John ?(切點方法為:public void demo04.advisor.Waiter.serverTo(java.lang.String))
Waiter Server to John
可以看出serveTo()和greetTo()都被織入了增強,但greetTo()內部呼叫的serverTo()沒有被織入增強。
3、原因分析
上面例子中,在greetTo()方法裡面直接呼叫serverTo(……)方法,這裡還隱含一個關鍵字,那就是this,實際上這裡呼叫是這樣的:this.serverTo(),this是當前物件。而呼叫greetTo()是的物件是被代理的,在代理物件中執行增強後,通過invoke,用實際Waiter物件來呼叫greetTo()方法執行業務邏輯。在業務邏輯內又呼叫了serverTo(……)方法,呼叫的物件是當前物件,當前物件是Waiter,問題就出在這裡,因為要想用執行serverTo方法的增強,必須用代理物件執行,但是此時卻直接用Waiter物件呼叫,繞過了代理物件增強的部分,也就是說代理增強部分失效。在同一個類中使用@Transaction,@Async並不能實現事務和非同步,道理就是這樣的。
相關文章
- Spring AOP呼叫本類方法沒有生效的問題Spring
- unity 模型無法繞自身中心旋轉Unity模型
- Spring事務失效的一種原因(this呼叫)Spring
- Spring中的AOP,以及宣告式事務 @Transactional無法攔截事務Spring
- hibernate無法自動建表的原因以及.sql檔案無法執行的原因SQL
- 本地無法連線Mysql的原因MySql
- Spring原始碼分析之AOP從解析到呼叫Spring原始碼
- File 物件呼叫 renameTo() 方法失敗原因物件
- Spring 的 AOPSpring
- Spring的AOPSpring
- UICollectionView SelectItem方法無效的原因UIView
- 印表機無法列印的原因與解決辦法
- Mac電腦無法透過有線上網的原因與解決方法Mac
- 在同一個類中呼叫另一個方法沒有觸發 Spring AOP 的問題Spring
- EM agent無法啟動的原因及分析
- 四、Spring的AOPSpring
- spring 的aop,急Spring
- Spring 中的AOPSpring
- Win10系統下無法識別硬碟的原因及解決方法Win10硬碟
- spring aop的兩種寫法aspect和advisorSpring
- Spring AOPSpring
- spring AOPSpring
- [Spring]AOPSpring
- Spring原始碼-AOP(六)-AOP代理的建立Spring原始碼
- Laravel 郵件無法傳送原因的查詢Laravel
- MySql事務無法回滾的原因有哪些MySql
- ADFS服務無法啟動的原因排查
- USB儲存裝置無法識別的原因
- Bootstrap 模態框無法呼叫的問題boot
- 電腦Hosts檔案修改後無法儲存的原因及解決方法教程
- dubbo 遠端服務無法呼叫
- 網路印表機無法連線的原因與解決辦法
- 死磕Spring之AOP篇 - Spring AOP總覽Spring
- Dcat Admin 使用 Laravel Octane 時匯出功能無法使用的原因及修復方法Laravel
- 企業無法留住技術人才的10大原因
- iOS中按鈕無法互動的5個原因iOS
- Spring AOP APISSpringAPI
- spring-aopSpring