当前位置: 首页 > 知识库问答 >
问题:

Spring AOP对于具有接口的类无能为力

瞿宏儒
2023-03-14

我知道Spring AOP的能力非常有限(它只能切入作为Spring bean的类的公共方法,并且只有当那些方法是从类外部调用时才可以)。但现在我发现了涉及接口时的另一个令人费解的限制。

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 Boot2,它使用了“新的”CGLIB策略。但是在SB1上,它可能仍然使用“旧的”动态JDK代理策略,因此它可能仍然不能在那里工作。

共有1个答案

益绯辞
2023-03-14

Spring将使用动态代理或cglib来实现AOP。

如果没有接口,则选择Cglib,那么它将有效地创建目标类的子类,并覆盖目标类中的所有方法。通过这种方式,除了final和static方法之外,所有方法都可以被插入。

如果目标类带有接口,那么Spring可能会使用一个使用接口的动态代理,并且类似地,这只会影响在接口中声明的方法。

在我看来spring可能会在你的案例中采用动态代理的方法。您可以在application.yaml中添加spring.aop.proxy-target-class:true来强制使用cglib。

如果您仍然有问题,最好发布更完整的代码片段,显示如何调用方法。

 类似资料:
  • 问题内容: 我正在学习如何使用JavaScript进行OOP。它具有接口概念(例如Java的接口)吗? 这样我就可以创建一个侦听器… 问题答案: 没有“此类必须具有这些功能”的概念(也就是说,本身没有接口),因为: JavaScript继承基于对象,而不是类。除非您意识到:这不是什么大不了的事情 JavaScript是一种 非常 动态的类型化语言-您可以使用适当的方法创建对象,这将使其符合接口,

  • 在学习静态编程语言中的泛型时,我在一本书中读到了以下内容: 通常,如果类具有将其用作返回类型的函数,或者如果类具有该类型的val属性,则类或接口泛型类型可以以out作为前缀。但是,如果类具有该泛型类型的函数参数或var属性,则不能使用out。 我理解规则所说的,但我很乐意(通过示例)理解没有此规则可能会有什么(即在声明泛型类/接口时使用out时没有约束),以及为什么返回类型可以来自类型t,而类/接

  • 问题内容: 在Java中,为什么不能在接口中使用受保护的方法? 由于根据Java规范 受保护的访问(由关键字protected表示)-同一包中任何类型以及任何包中的子类均可访问的字段或方法。 如果我必须使用该接口,那么我将实现它并覆盖方法。因此,如果我要实现类可以访问这些方法的位置,因为该方法可以在任何包中访问。那么,将方法声明为Interface中的保护有什么害处? 问题答案: 受保护的方法旨在

  • 为什么我不能这样做?我得到编译错误。 那是Java8 我不认为这里违反了任何OO原则。 这真的让我很难实现通用 API...... (我试图将泛型从游戏中剔除,因为泛型API变得反直觉了)

  • 问题内容: 根据Hibernate文档的这一部分,我应该能够查询HQL中的任何Java类。 http://docs.jboss.org/hibernate/core/3.3/reference/en/html/queryhql.html#queryhql- polymorphism 不幸的是,当我运行此查询时… 我收到消息“未映射事务[[从事务trans,其中trans.envelopeId =:

  • 问题内容: 在Java 8中,只有一个抽象方法的抽象类不是功能接口(JSR 335 )。 这是一个功能接口: 但这不是: 因此,我不能将抽象类用作lambda表达式和方法引用的目标。 编译错误为:。 语言设计者为什么要施加此限制? 问题答案: 自Lambda项目成立以来,这一直是一个重要的话题,并且引起了很多思考。Java语言首席架构师Brian Goetz强烈支持将lambda视为 功能 而非