问题描述
我正在尝试定义一个方面来注入记录器。
我正在寻找类似的东西
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("{}.{} = {}",result);
}
}
为此,我要检索执行元数据/上下文数据:
- 例外
- 返回值
如何获取此元数据/上下文数据?
解决方法
为了保持您的方面高效,我建议以下内容:
- 将切入点限制为您真正希望调试的目标包和类。不要记录/追踪整个世界。您还可以将抽象基础方面与抽象切入点一起使用,并将方面扩展为具有具体切入点的具体子方面。如果您使用加载时间编织,甚至可以通过XML配置提供后者。
- 使用
around()
建议而不是before()
/after()
对。然后,您只需要计算一些记录的值,并在通过proceed()
完成原始方法调用之前和之后使用它们。 - 仅记录
thisJoinPoint
而不是默认情况下将其中包含的位拼凑在一起。这将为您提供连接点的类型,方法签名(包括参数类型和返回值)。 - 不记录参数名称,该信息不增加任何实际值。此外,参数名称可以进行重构,并且仅当您的代码是使用调试信息编译的时候才存在。保持简单,只记录参数值。
- 在上述
around()
建议中,您可以将proceed()
调用包含到try-catch-finally
中,并方便地处理和记录任何异常和堆栈跟踪,和/或将检查的异常包装到AspectJ的{{1 }}或简单的SoftException
并重新抛出它们。无论哪种情况都适合您。 - 方法调用结果只是
RuntimeException
的结果,这也是您从proceed()
建议中返回的结果。如果出于某种原因希望跳过目标方法的执行,也可以返回其他内容(但必须具有正确的返回类型)或完全跳过around()
。
我刚才说的所有内容都写在AspectJ手册或任何其他AspectJ教程中。您可能想在下次问像这样的一般问题之前阅读其中的一些内容。