我听说AOP如何帮助模块化日志记录等很多很棒的事情,但现在我正在努力实现这一点,我发现AspectJ非常有限。
有时不仅无法将记录添加到正确的行,而且访问局部变量值似乎非常困难。您必须确保变量由方法返回或用作方法的参数。
日志记录超出了记录代码范围的简单事实是一个严重的限制。
是否有更好的方法来访问本地变量值以进行记录?
例如,我有一些维护计数器的代码,我想记录该计数器的值。原始代码看起来像这样:
int totalMoves = 0;
while(canMove()) {
// ...
totalMoves++;
}
Logger.log(totalMoves);
我找不到 clean 方法将此日志记录代码移动到某个方面。根本无法访问totalMoves
。看来我的选择是:
totalMoves
成为可公开访问的字段(与信息隐藏和封装相对)totalMoves
成为私有字段,但使用反射来访问它(看起来像是一个糟糕的代码气味;创建一个不必要的字段并使访问变量变得复杂)老实说,我想在查看AOP时我所期待的是逐字插入代码以消除交叉问题。这些限制让我怀疑AspectJ是否值得在当前环境中使用。
还有这个问题吗?或者我是以错误的方式接近这个?在这种情况下,我如何干净地记录局部变量?
TL; DR:使用AspectJ记录局部变量值是一团糟,我怎样才能让它更好?
答案 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;
}