使用 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 数据:
- 例外情况
- return 值
如何获取此 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 教程中。下次问这样的一般性问题之前,您可能想阅读其中的一些内容。
我正在尝试定义一个方面来注入记录器。
我想创建类似这样的东西:
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 数据:
- 例外情况
- return 值
如何获取此 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 教程中。下次问这样的一般性问题之前,您可能想阅读其中的一些内容。