使用AspectJ记录局部变量值

时间:2014-07-16 00:55:59

标签: logging aspectj aop

我听说AOP如何帮助模块化日志记录等很多很棒的事情,但现在我正在努力实现这一点,我发现AspectJ非常有限。

有时不仅无法将记录添加到正确的行,而且访问局部变量值似乎非常困难。您必须确保变量由方法返回或用作方法的参数。

日志记录超出了记录代码范围的简单事实是一个严重的限制。

是否有更好的方法来访问本地变量值以进行记录?

例如,我有一些维护计数器的代码,我想记录该计数器的值。原始代码看起来像这样:

int totalMoves = 0;

while(canMove()) {
    // ...
    totalMoves++;
}

Logger.log(totalMoves);

我找不到 clean 方法将此日志记录代码移动到某个方面。根本无法访问totalMoves。看来我的选择是:

  1. 使totalMoves成为可公开访问的字段(与信息隐藏和封装相对)
  2. 创建一个虚拟函数,除了允许AspectJ的“钩子”之外什么都不做(不比直接记录更好)
  3. 使totalMoves成为私有字段,但使用反射来访问它(看起来像是一个糟糕的代码气味;创建一个不必要的字段并使访问变量变得复杂)
  4. 老实说,我想在查看AOP时我所期待的是逐字插入代码以消除交叉问题。这些限制让我怀疑AspectJ是否值得在当前环境中使用。

    还有这个问题吗?或者我是以错误的方式接近这个?在这种情况下,我如何干净地记录局部变量?

    TL; DR:使用AspectJ记录局部变量值是一团糟,我怎样才能让它更好?

2 个答案:

答案 0 :(得分:2)

之前已多次询问此问题。答案是不。 AspectJ不能拦截局部变量的读/写操作,只能拦截成员。此外,在某些情况下,JVM可能会优化掉一些处理局部变量的源代码,但这是另一个主题。

滥用这样的AOP框架无论如何都不是一个好主意,即使它是可能的。它们用于装饰具有附加功能的类或拦截一些可从外部访问的操作,而不是用于攻击本地状态。如果一个方面需要知道局部变量名,它对你的应用程序设计有何看法?

至于你提到的三个选项,它们并不是你唯一拥有的选项。您还可以将totalMoves设为私有字段,并在有意义的情况下提供getter和/或setter。此外,即使您决定不使用getter / setter,您仍然可以使用能够与privileged aspect一起访问私有或受保护字段的get|set() pointcuts

在阅读提供的链接后,请随意询问您是否理解此答案。

答案 1 :(得分:0)

另一种选择是重构代码的一部分并从中提取方法,并添加一个记录其返回值的方面:

@Log
private int totalMoves() {
    int totalMoves = 0;

    while(canMove()) {
        // ...
        totalMoves++;
    }

    return totalMoves;
}