一个类实现接口并且继承父类 使用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();

    }
}

image.png

当我删除Child 实现的接口方法是可以aop可以扫描到对应的子类

@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();
//
//    }
}

image.png

请问这种子类即实现了接口又覆盖了父类的方法, spring aop 会采用那种方式实现,出现上述问题的原因是什么?

阅读 533
avatarAI BotBETA

回答

在Spring AOP中,当一个类既实现了接口又继承了父类时,Spring AOP默认使用JDK动态代理(针对接口)或CGLIB代理(针对类)。具体使用哪种代理方式取决于目标对象的配置和Spring AOP的默认行为。

问题原因

  1. JDK动态代理限制

    • 当一个类实现了接口,并且你希望对该类的方法进行AOP增强时,Spring AOP默认会使用JDK动态代理。
    • JDK动态代理只能代理接口方法,不能代理类方法。因此,如果Child类中的方法是通过接口Run定义的(如runs()方法),并且你希望对这些方法进行AOP增强,那么这些增强将仅适用于接口方法。
    • 如果Child类中的方法(如test()test2()say())是继承自父类Parent的,并且这些父类方法不是接口方法,那么这些方法的AOP增强将依赖于CGLIB代理。
  2. CGLIB代理限制

    • CGLIB代理是通过继承目标类来创建代理对象的。因此,如果目标类已经有一个父类,CGLIB代理将创建一个该目标类的子类。
    • 如果目标类(如Child)已经是一个具体的类(不是抽象类),并且它继承了另一个类(如Parent),那么CGLIB代理将正常工作,前提是没有违反Java的单继承规则。
  3. AOP配置问题

    • 如果AOP配置不正确(如切点表达式不正确、切面类没有被Spring容器管理等),那么AOP增强将不会生效。
    • 确保你的切面类(包含@Aspect注解的类)被Spring容器管理,并且切点表达式正确匹配了你想要增强的方法。
  4. 方法可见性和访问权限

    • 确保被增强的方法是可见的(即不是私有的),因为AOP代理需要能够访问这些方法。

解决方案

  • 确保AOP配置正确:检查你的切面类和切点表达式,确保它们正确无误。
  • 使用正确的代理方式:如果你需要增强接口方法和类方法,确保你的Spring配置启用了CGLIB代理(通常这是默认启用的,但可以通过配置进行调整)。
  • 检查方法访问权限:确保被增强的方法具有适当的访问权限。
  • 调试和日志:启用Spring AOP的调试日志,以查看代理的创建过程和切点的匹配情况。

在你的具体情况下,如果runs()方法是通过接口Run定义的,并且你希望对其进行AOP增强,那么你应该确保你的AOP配置能够处理接口方法的增强。如果test()test2()say()方法是通过继承自父类Parent的,并且你希望对这些方法进行AOP增强,那么你应该检查CGLIB代理是否正在被正确使用。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏