使用Eclipse AspectJ注入一个Logger,记录执行代码的上下文/元数据



我正在尝试定义一个方面来注入记录器。

我希望创建类似的东西:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public aspect LogInjector {
private pointcut executionJoinPoints(): !within(LogInjector) && execution (* *.*(..));
before(): executionJoinPoints(){
// Get class name of the executed code
clazz = ...
final Logger logger = LogManager.getLogger(clazz);
// Get method name of the executed code
method = ...
// Get params name, type and values triplet or values at least if the previous is not possible, of the executed code
params = ...
// Get call stack of the executed code
stack = ...
logger.trace("{}.{}({}) - {}", clazz.name(), method.name(), params, stack);
}
after(): executionJoinPoints(){
// Get class name of the executed code
clazz = ...
final Logger logger = LogManager.getLogger(clazz);
// Get method name of the executed code
method = ...
// Get return value or exception of the executed code
result = ...
logger.trace("{}.{} = {}", clazz.name(), method.name(), result);
}
}

为此,我想检索执行元数据/上下文数据:

  • 异常
  • 返回值

如何获取此元数据/上下文数据?

为了保持方面的效率,我建议如下:

  • 将切入点限制为您真正希望调试的目标包和类。不要记录/追踪整个世界。您还可以使用带有抽象切入点的抽象基本方面,并将该方面扩展为带有具体切入点的具体子方面。如果使用加载时编织,后者甚至可以通过XML配置提供
  • 使用around()建议,而不是before()/after()对。然后,您只需要计算一些记录的值一次,并在通过proceed()进行原始方法调用之前和之后使用它们
  • 只需记录thisJoinPoint,而不是默认情况下将其中包含的位拼接在一起。这已经为您提供了连接点的类型、方法签名,包括参数类型和返回值
  • 不要记录参数名称,这些信息不会增加任何实际值。此外,参数名称需要进行重构,并且只有在使用调试信息编译代码时才会出现。保持简单,只记录参数值
  • 在上面提到的around()建议中,您可以将proceed()调用封装到try-catch-finally中,方便地处理和记录任何异常以及堆栈跟踪和/或将检查的异常封装到AspectJ的SoftException或简单的RuntimeException中,然后重新抛出它们。适用于您情况的任何内容
  • 方法调用结果只是proceed()的结果,这也是您需要从around()建议中返回的结果。您也可以返回其他内容(但它必须具有正确的返回类型(,或者如果出于任何原因希望跳过目标方法执行,则完全跳过proceed()

我刚才说的所有内容都写在AspectJ手册或任何其他AspectJ教程中。在问这样一个一般性问题之前,你可能想下次读一些。

最新更新