首页 > 解决方案 > 使用 Eclipse AspectJ 注入记录代码执行的上下文/元数据的记录器?

问题描述

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

我正在寻找类似的东西:

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

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

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

标签: javaaopaspectj

解决方案


为了使您的方面保持高效,我建议以下内容:

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

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


推荐阅读