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
- Spring事務失效的一種原因(this呼叫)Spring
- unity 模型無法繞自身中心旋轉Unity模型
- Spring原始碼分析之AOP從解析到呼叫Spring原始碼
- 本地無法連線Mysql的原因MySql
- UICollectionView SelectItem方法無效的原因UIView
- Spring 的 AOPSpring
- File 物件呼叫 renameTo() 方法失敗原因物件
- [Spring]AOPSpring
- spring AOPSpring
- Bootstrap 模態框無法呼叫的問題boot
- 死磕Spring之AOP篇 - Spring AOP總覽Spring
- 快看!5S無法落地的原因找到了
- MySql事務無法回滾的原因有哪些MySql
- Laravel 郵件無法傳送原因的查詢Laravel
- Dcat Admin 使用 Laravel Octane 時匯出功能無法使用的原因及修復方法Laravel
- 電腦Hosts檔案修改後無法儲存的原因及解決方法教程
- Spring Boot整合Spring AopSpring Boot
- spring-aopSpring
- Spring AOP APISSpringAPI
- Spring AOP IOCSpring
- Spring MVCD框架中呼叫HanLP分詞的方法SpringMVC框架HanLP分詞
- Spring AOP的AspectJ註解Spring
- Spring AOP的實現原理Spring
- Jtti:c++無法啟動程式的原因有哪些JttiC++
- 無法遠端連線vps 伺服器的原因伺服器
- Spring @Retryable重試方法呼叫詳解Spring
- 這一次搞懂Spring代理建立及AOP鏈式呼叫過程Spring
- 提高自身Java開發能力的方法?Java
- Spring框架系列(10) - Spring AOP實現原理詳解之AOP代理的建立Spring框架
- 帝國CMS系統開啟https後,無法登陸後臺的原因和解決方法HTTP
- python無法匯入包是什麼原因Python
- Spring雜談 | 從橋接方法到JVM方法呼叫Spring橋接JVM
- Spring系列.AOP使用Spring
- Spring AOP 掃盲Spring
- Spring——AOP實現Spring
- Spring 面向切面AOPSpring
- Spring aop練手Spring