[英]Spring AOP is powerless for classes with interfaces
我知道Spring AOP的功能非常有限(它只能切入Spring bean的類的公共方法,並且只有在從類外部調用這些方法時)。 但是現在我發現了涉及接口的另一個令人困惑的限制。
通常,如果一個類被子類化,Spring AOP可以切入所有方法(甚至是被覆蓋的方法):
public class A {
public void methodA() { } //OK, can cut in
}
public class B extends A {
@Override
public void methodA() { } //OK, can cut in
public void methodB() { } //OK, can cut in
}
但是當我們在混合中添加一個接口時,對於Spring AOP來說,事情變得非常糟糕:
public interface I {
public void methodA();
}
public class A implements I {
@Override
public void methodA() { } //OK, can cut in
public void methodB() { } //Fail, cannot see or cut into this method
}
public class B extends A {
@Override
public void methodA() { } //Fail, cannot see or cut into this method
public void methodC() { } //Fail, cannot see or cut into this method
}
首先,Spring AOP只能切入界面中的方法,其他任何東西 - 它都看不到。 其次,它只能切入直接實現接口方法的方法 - A.methodA()
。 它無法切入由B覆蓋的相同方法。
我使用通用切入點表達式"execution(* method*(..))"
來切入所有可能的方法,因此它不是表達式問題。
這種限制有什么辦法嗎? 或者我應該忘記Spring AOP並使用不同的方法?
更新:好的,我找到了問題的真正原因。 我實際上是依靠Intellij IDEA的AOP插件來測試它。 它應該將切入點鏈接到所有受影響的方法。 但它使用的是“舊的”動態JDK代理策略,而不是新的CGLIB策略。 所以它沒有將它鏈接到所有方法,但是當我實際運行我的程序時,它會正確地切入所有方法。
我正在使用Spring Boot 2,它使用'新'CGLIB策略。 但是在SB1上它可能仍然使用“舊的”動態JDK代理策略,因此它可能仍然無法在那里工作。
Spring將使用動態代理或cglib來實現AOP。
如果沒有接口,則選擇Cglib,然后它將有效地創建目標類的子類,並覆蓋目標類中的所有方法。 通過這種方式,除最終和靜態方法外,所有方法都可以切入。
如果目標類是帶接口的,那么Spring可能會使用其中一個接口使用動態代理,顯然這只會影響接口中聲明的方法。
在spring-boot 2.0之前,動態代理是默認策略。 現在Cglib是spring-boot 2.0之后的默認策略。
在我看來,Spring可能會采用動態代理方法。 您可以在application.yaml中添加spring.aop.proxy-target-class:true以強制使用Cglib。
如果您仍有問題,最好發布更完整的代碼段,顯示如何調用mothods。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.