使用 Eclipse AspectJ 注入一个 Logger 来记录代码执行的 context/meta 数据?

Using Eclipse AspectJ to Inject a Logger which Logs context/meta data of the code execute?

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

我想创建类似这样的东西:

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

为此,我想检索执行 metadata/context 数据:

如何获取此 metadata/context 数据?

为了让你的看点保持高效,我推荐如下:

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

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