AspectJ-组合方法注释和设置字段

时间:2017-02-27 17:07:17

标签: java aop aspectj spring-aop

我有一个要求,我需要将各种方法调用计入时间序列db。

同样,我为方法调用创建了一个注释:

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

    String event();
    String entity();
}

和另一个字段

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Id {
   String id();
}

我需要@ID注释的原因是,只有在运行时才能知道要推送到流入数据库的id字段。

所以,在我的方法中,会发生类似这样的事情:

@Id
String key;

@Auditable(event="xxx",entity="yyy")
public void methodToBeIntercepted(){
   String key = <logic to generate key>;
}

我想要使用的想法是添加注释建议以及字段集建议。

@After("@annotation(auditable) && (set(@<package>.ID java.lang.String sample..*.*) && args(id))")
public void pointcutMethod(Auditable auditable,String id){
}

但是流程永远不会进入pointCutMEthod。如果我将条件改为||然后它进入,但它清楚地表明在任何给定的时间点只有1个条件是真的。

我在这里做错了什么?

1 个答案:

答案 0 :(得分:0)

您的分析是正确的:建议永远不会触发。它只是不能,因为你组合的两个切入点是互斥的:@Auditable是(方法调用或执行)是set()的不同连接点。您打算表达的内容如下:“在方法执行的 控制流 中拦截成员变量。”即你需要cflow(@annotation(auditable))

注释和驱动程序应用程序:

package de.scrum_master.app;

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

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Id {
  String id();
}
package de.scrum_master.app;

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Auditable {
  String event();
  String entity();
}
package de.scrum_master.app;

public class Application {
  @Id(id = "my ID")
  String key;

  public static void main(String[] args) {
    Application application = new Application();
    application.methodToBeIntercepted();
  }

  @Auditable(event = "xxx", entity = "yyy")
  public void methodToBeIntercepted() {
    key = "I am the key";
  }
}

<强>方面:

package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;

import de.scrum_master.app.Auditable;

@Aspect
public class MyAspect {
  @After("cflow(@annotation(auditable)) && set(@de.scrum_master.app.Id String de.scrum_master..*.*) && args(id)")
  public void pointcutMethod(JoinPoint thisJoinPoint, Auditable auditable, String id) {
    System.out.println(thisJoinPoint);
    System.out.println("  " + auditable);
    System.out.println("  " + id);
  }
}

控制台日志:

set(String de.scrum_master.app.Application.key)
  @de.scrum_master.app.Auditable(event=xxx, entity=yyy)
  I am the key