AspectJ 关于具有字段的 class 方法的建议

AspectJ advice on method of a class that has a field

我想写一个绕过建议,在调用 proceed() 之前将 correlation-id 设置到 MDC 中,并 return 在它之后的旧值。这是我的进展:

public aspect CorrelationIdAspect
{
    private pointcut notPrivateMethod() :
        execution(!private * *(..));
    
    private pointcut methodWithContract(Contract contract) :
        execution( * *.*(Contract, ..)) && args(contract, ..);
    
    Object around(Contract contract) : methodWithContract(contract) && notPrivateMethod()
    {
        String oldCorrelationId = MDC.get(Constants.CORRELATION_ID);
        try
        {
            String id = contract.getId().toString();
            MDC.put(Constants.CORRELATION_ID, id);
            Object result = proceed(contract);
            return result;
        }
        finally
        {
            MDC.put(Constants.CORRELATION_ID, oldCorrelationId);
        }
    }
}

现在我希望此建议仅应用于 class 具有类型

的字段

org.apache.logging.log4j.Logger

因为 - 显然 - 没有记录器的 class 不需要设置和恢复相关 ID。有人知道如何实现吗?

非常感谢!

您想使用编译器选项 -XhasMember(另请参阅 my other answer),可在 Eclipse 中找到:

那你

  1. 为你的方面添加一个标记界面,
  2. 使用 ITD 来声明每个具有 static Logger 字段的 class 应该实现该接口并且
  3. 匹配标记接口及其所有实现 classes:
public aspect CorrelationIdAspect {
  // 1. marker interface 
  private interface HasLogger {}

  // 2. use ITD in order to declare that each class having a
  // 'static Logger' field ought to implement that interface
  declare parents :
    hasfield(static Logger *) implements HasLogger;

  private pointcut notPrivateMethod() :
    execution(!private * *(..));

  // 3. match on the marker interface and all its implementing classes
  private pointcut hasLogger() :
    within(HasLogger+);

  private pointcut methodWithContract(Contract contract) :
    execution(* *(Contract, ..)) && args(contract, ..);

  Object around(Contract contract) :
    methodWithContract(contract) && notPrivateMethod() && hasLogger()
  {
    System.out.println(thisJoinPoint);
    return proceed(contract);
  }
}