簡體   English   中英

Spring AOP對於具有接口的類無能為力

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM