如果注释不存在则执行AOP

时间:2016-11-08 17:23:23

标签: java annotations aop spring-aop

我正在使用AOP来围绕某些服务包装审计框架。我遇到过一个问题,即由于递归,我们会针对同一操作审核多个事件。快速解决方法将方法标记为@NonAuditable并将其添加到我的切入点策略中。我发现该方法仍然被执行。

这是我现有的策略:

@Around(value="(" +
     "execution( * my.class.services..*.*(..)) " +
     ") && "+
     "@annotation(auditable)), argName="audit")
     public Object audit(ProceedingJoinPoint call, Audit audit) {
       ...
       ...
     }

如何更新我的执行以表示"只有在不包含@NonAuditable注释的服务包中执行?

我尝试了以下操作,但没有效果:

@Around(value="(" +
 "execution( * my.class.services..*.*(..)) " +
 ") && "+
 "!@annotation(NonAuditable) && " +
 "@annotation(auditable), argName="audit")
 public Object audit(ProceedingJoinPoint call, Audit audit) {
   ...
   ...
 }

更新:

以下是一些获得审核的方法的一些示例

package my.class.services.UserService
import ...
...

@Auditable(message="Request for user", Context="Search")
public User getUser(long id){
      User u = userRepository.getUser(id);
      ... // do work
}  

\

package my.class.services.CarService
import ...
...

@Auditable(message="Request for traffic violations", Context="Search")
public List<Ticket> getTickets(long id){
      List<Ticket> tix = dmvRepository.getUserTicketsById(id);
      ... // do work
}

@NonAuditable(message="Request for traffic violations", Context="Search")
public List<Ticket> getSpeedingTickets(long id){
      List<Ticket> tickets = this.getTickets(id);
      Collection filter = Collection.filter(...);
      // do some other logic to just get speeding tickets.
      return filter;
}

我继承的一个问题是getTickets被另一个方法(getSpeedingTickets)递归调用,我希望能够在该方法上应用Annotation@NonAuditable)阻止getTickets被审核。

1 个答案:

答案 0 :(得分:0)

好的,我又想了想,我想我已经猜到了你的意思。我认为你的情况是这样的:

<强>注解

package de.scrum_master.app;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface Auditable {}
package de.scrum_master.app;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface NonAuditable {}

驱动程序应用程序:

package de.scrum_master.app;

public class Application {
    public static void main(String[] args) {
        Application application = new Application();
        application.auditableAction("main");
        application.inBetweenAction("main");
        application.otherAction();
        application.nonAuditableAction();
    }

    @Auditable
    public void auditableAction(String caller) {
        System.out.println("  auditableAction called by " + caller);
    }

    @NonAuditable
    public void nonAuditableAction() {
        auditableAction("nonAuditableAction");
        inBetweenAction("nonAuditableAction");
    }

    public void otherAction() {
        auditableAction("otherAction");
        inBetweenAction("otherAction");
    }

    public void inBetweenAction(String caller) {
        auditableAction(caller + " via inBetweenAction");
    }
}

现在我假设您希望避免在@Auditable方法直接或间接调用时审核@NonAuditable方法的执行。正确?如果是这样,解决方案是使用cflow()cflowbelow()切入点。由于此类切入点无法静态评估,但仅在运行时动态评估,因此您可能需要在应用方面后监视应用程序的性能,但在许多情况下,这不是一个真正的问题。你自己看。解决方案如下:

<强>方面:

package de.scrum_master.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AuditAspect {
    @Around(
        "within(de.scrum_master.app..*) && " +
        "execution(* *(..)) && " +
        "@annotation(de.scrum_master.app.Auditable) && " +
        "!cflow(@annotation(de.scrum_master.app.NonAuditable))"
    )
    public Object audit(ProceedingJoinPoint thisJoinPoint) throws Throwable {
        System.out.println(thisJoinPoint);
        return thisJoinPoint.proceed();
    }
}

控制台日志:

execution(void de.scrum_master.app.Application.auditableAction(String))
  auditableAction called by main
execution(void de.scrum_master.app.Application.auditableAction(String))
  auditableAction called by main via inBetweenAction
execution(void de.scrum_master.app.Application.auditableAction(String))
  auditableAction called by otherAction
execution(void de.scrum_master.app.Application.auditableAction(String))
  auditableAction called by otherAction via inBetweenAction
  auditableAction called by nonAuditableAction
  auditableAction called by nonAuditableAction via inBetweenAction

请注意,在最后两行之前没有记录任何内容。