首页 > 解决方案 > 关于具有字段的类的方法的 AspectJ 建议

问题描述

我想写一个环绕建议,在调用proceed()之前将相关ID设置为MDC,并在它之后返回旧值。这是我走了多远:

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);
        }
    }
}

现在我希望这个建议只应用于具有类型字段的类

org.apache.logging.log4j.Logger

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

提前谢谢了!

标签: aspectj

解决方案


您想使用编译器选项-XhasMember(另请参阅我的其他答案),可以在 Eclipse 中找到:

Eclipse AspectJ 编译器选项

然后你

  1. 为你的方面添加一个标记界面,
  2. 使用 ITD 来声明每个具有static Logger字段的类都应该实现该接口,并且
  3. 在标记接口及其所有实现类上匹配:
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);
  }
}

推荐阅读