【问题标题】:AOP with custom annotation in Super class doesn't work超类中带有自定义注释的 AOP 不起作用
【发布时间】:2016-02-28 07:55:38
【问题描述】:

自定义注释

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomAnnotation {
}

自定义注释处理程序

@Aspect
public class TestAspectHandler {
    @Around("execution(@com.test.project.annotaion.CustomAnnotation * *(..)) && @annotation(customAnnotation)")
    public Object testAnnotation(ProceedingJoinPoint joinPoint, CustomAnnotation customAnnotation) throws Throwable {
        System.out.println("TEST");
        return result;
    }
}

超类

public class AbstractDAO {
     @CustomAnnotation
     protected int selectOne(Object params){
          // .... something
     }
}

子类

public class SubDAO extends AbstractDAO {
    public int selectSub(Object params) {
         return selectOne(params);
    }
}

子类 SubDAO 调用 SuperClass 方法 selectOne 但在 TestAspectHandler.class 中不调用 testAnnotation(...)

当我将@CustomAnnotation 移动到子类selectSub(..) 方法AspectHandler 可以得到joinPoint

如何在超类保护方法中使用自定义注解?


added

更改TestAspectHandler.testAnnotation(...) method

@Around("execution(* *(..)) && @annotation(customAnnotation)")
public Object testAnnotation(ProceedingJoinPoint joinPoint, CustomAnnotation customAnnotation) throws Throwable {
            System.out.println("TEST");
            return result;
}

还是不行

所以我在代码下更改我的SubDAO

public class SubDAO extends AbstractDAO {
    @Autowired
    private AbstractDAO abstractDAO;
    public int selectSub(Object params) {
         return abstractDAO.selectOne(params);
    }
}

这不是完美的解决方案,但它确实有效


  • 案例1:从子类方法调用超类方法不起作用
  • 案例 2:创建 Super 类实例并从实例调用

【问题讨论】:

  • 如果您已经阅读了我的回答,请同时阅读编辑/更新。现在有新信息。
  • Spring AOP 使用代理工作,只有对对象的方法调用通过代理,您正在执行内部方法调用,因此它不通过代理,因此不应用 AOP .除此之外,即使它会应用实际方法也不会被调用,因为你的周围方面会破坏它。

标签: java spring aspectj spring-aop


【解决方案1】:

首先,我希望你的DAO类是真正的Spring组件,否则Spring AOP找不到它们,只有AspectJ可以。

但它的核心不是 Spring 或 AspectJ 问题。在 Java 中,注释在

  • 接口,
  • 其他注释或
  • 方法

永远不会被继承

  • 实现类,
  • 使用带注释的类或
  • 重写方法。

注解继承仅适用于从类到子类,但前提是超类中使用的注解类型带有元注解@Inherited,参见JDK JavaDoc

因为我之前已经多次回答过这个问题,所以我刚刚记录了这个问题以及Emulate annotation inheritance for interfaces and methods with AspectJ中的解决方法。


更新:抱歉,我刚刚更彻底地检查了您的代码。您没有覆盖超类的注释方法(至少您的代码没有显示您覆盖了方法selectOne),所以我上面描述的内容不适用于这里。你的方面应该工作。但也许你只是在完全限定的类名@com.test.project.annotaion.CustomAnnotation 中有错字:annotaion(请注意错字!)包名可能应该是annotation。正如我在第一句话中所说:DAO 必须是 Spring @Components。

顺便说一句:您可以完全避免切入点的那部分,因为您已经将注释绑定到参数。只需使用

@Around("execution(* *(..)) && @annotation(customAnnotation)")

【讨论】:

  • 谢谢,但 Around("execution(* *(..)) && @annotation(customAnnotation)") 不起作用 :( 阅读更新的问题
  • 那么你的 Spring 配置有问题。两个 DAO 真的都是 Spring 组件吗?正如我所说:Spring AOP 在 POJO 上工作。
  • 是的,如果有 POJO,两个 DAO 都是 Spring 组件不能使用 @Autowired
  • 您的解决方法没有意义。为什么要使用继承,然后将父对象分配给成员?找到根本原因,解决问题!
  • 您的权利。但真的不知道为什么它不起作用:(。案例 2 有效,但案例 1 无效
【解决方案2】:

它的工作方式是你的 spring bean 代理(对 spring bean 的每个引用实际上是一个代理,它委托给 bean 实例)为你创建 JDK Dynamoc 代理(对于实现至少 1 个接口或 CGLib 代理的类)应用方面。所以调用selectSub方法时,已经通过了spring bean的委托,不能应用切面。 如果你想让它工作,你还必须注释 sub 方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-18
    • 2021-03-28
    • 1970-01-01
    • 1970-01-01
    • 2017-12-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多