在Super class中使用自定义注释的AOP不起作用

时间:2016-02-28 07:55:39

标签: java spring aspectj spring-aop

自定义注释

@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:制作超级类实例并从实例调用

2 个答案:

答案 0 :(得分:3)

首先,我希望您的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 @Component s。

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

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

答案 1 :(得分:0)

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