AspectJ-结合方法注解和集合字段

AspectJ- combining method annotation and set field

我有一个要求,我需要将各种方法调用计时到时间序列数据库中。

同样,我创建了 2 个注释,其中一个用于方法调用:

@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 注释的原因是,要推送到 influx db 的 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 个条件为真。

我这里哪里做错了?

您的分析是正确的:建议永远不会触发。它只是不能,因为您组合的两个切入点是互斥的:@Auditable 所在的位置(方法调用或执行)是与 set() 不同的连接点。您打算表达的内容如下:"Intercept member variable assignment within the control flow of a method execution." 即你需要 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