繁体   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