為什么Spring AOP在子類實現接口并繼承父類時會失效?

為什么Spring AOP在子類實現接口并繼承父類時會失效?

探討spring AOP在子類實現接口繼承父類時失效的原因

在開發過程中,當我們使用Spring AOP對一個子類進行增強時,如果該子類同時實現了接口并繼承了父類,可能會遇到AOP切點失效的問題。讓我們通過一個具體案例來分析這種情況的表現及其原因。

問題描述

假設我們有一個類結構如下:

public interface Run {     public void runs(); }
public abstract class GrandFather {     public abstract void say(); }
public abstract class Parent extends GrandFather implements Run {      public abstract void test();      public void test2(){         System.out.println("父類方法");     } }
@Component public class Child extends Parent {      @OpenDefaultNameMark     public void test(){         System.out.println("Child");     }      @Override     @OpenDefaultNameMark     public void test2() {         System.out.println("子類方法");     }      @Override     @OpenDefaultNameMark     public void say() {      }      @Override     public void runs() {         // this.say();     } }

在上述結構中,Child類既繼承了Parent類,又實現了Run接口。同時,Child類重寫了父類的一些方法,并在這些方法上使用了自定義注解@OpenDefaultNameMark來進行AOP增強。然而,我們發現當Child類實現了Run接口的方法runs()時,AOP切點似乎失效了。

問題分析

為了驗證AOP是否真的失效,我們嘗試刪除Child類中實現的runs()方法:

@Component public class Child extends Parent {      @OpenDefaultNameMark     public void test(){         System.out.println("Child");     }      @Override     @OpenDefaultNameMark     public void test2() {         System.out.println("子類方法");     }      @Override     @OpenDefaultNameMark     public void say() {      }      // @Override     // public void runs() {     //     // this.say();     // } }

通過刪除runs()方法,我們發現AOP切點再次生效。這表明問題確實與Child類實現的接口方法有關。

問題原因

從AOP的實現機制來看,這種情況的問題出在AOP代理的生成方式上。Spring AOP使用動態代理來生成AOP代理類,當一個類同時實現接口和繼承類時,Spring會選擇基于接口的JDK動態代理,而不是基于類的CGLIB代理。而JDK動態代理是基于接口的代理機制,這可能會導致對類方法的AOP增強失效。

此外,根據你的描述,AOP的AspectJ代碼并沒有問題,問題的出現可能是由于插件的限制。插件在分析SpringBootApplicationContext時,依賴于Actuator的beans接口的返回值,這可能會導致插件無法準確反映AOP代理的實際情況。為了確保插件能夠正確反映AOP的生效情況,你需要在idea中啟動一次項目,使插件能夠刷新并獲取最新的AOP代理信息。

結論

在Spring AOP中,當一個子類既實現了接口又覆蓋了父類的方法時,AOP切點可能會失效。這是因為Spring可能選擇了基于接口的JDK動態代理,而這種代理機制可能無法正確處理類方法的AOP增強。為了解決這個問題,可以嘗試使用CGLIB代理,或者在IDEA中啟動項目以確保插件能夠正確反映AOP的實際效果。

? 版權聲明
THE END
喜歡就支持一下吧
點贊15 分享