我本质上是试图跟踪Account类的转账数量。在此处阅读文档:https://www.eclipse.org/aspectj/doc/released/progguide/language-anatomy.html在此处的幻灯片48和49上:https://www.eclipse.org/aspectj/doc/released/progguide/language-anatomy.html
这些告诉我,我应该能够做这样的事情:
public aspect LoggingAspect {
private int Account.transferCount = 0;
private int Account.getTransferCount() {
return transferCount;
}
pointcut firstTransfer(Account s, double amount):
withincode(public void transfer (int, int, double))
&& call(public boolean withdraw(int,double))
&& target(s)
&& args(amount);
boolean around(Account s, double amount):
firstTransfer(s, amount){
s.transferCount++; // Not recognized
if (s.getTransferCount() == 0) { // Not recognized
System.out.println("50% markup");
return s.deposit(amount*.5);
}
return false;
}
}
但是,如上面的代码中所述,在方面中,这些字段未被识别为存在于类中。我在做什么错?
我得到的错误是:transferCount cannot be resolved or is not a field
Account
类中发生了某些事情,很遗憾您没有在这里分享。请了解什么是MCVE以及为什么总是提供它是如此有价值。尤其是在AOP的情况下,这一点尤为重要,因为如果没有目标类,一个方面就没有多大意义。我不能调试一个而没有另一个,这就是为什么我必须发明自己的虚拟类。那实际上是您的工作。
[您可能正在尝试直接从Account
类中使用声明的私有成员。由于某种原因,我尚不了解,这不起作用,因为它以The method getTransferCount() from the type Account is not visible
或类似的错误消息抛出了AspectJ编译器。这必须是AspectJ中的限制或错误,我将要求维护者并在以后报告。
但是首先让我们重现您的情况:
应用程序类:
package de.scrum_master.app;
public class Account {
public void transfer(int a, int b, double c) {
withdraw(a, c);
}
public boolean withdraw(int a, double c) {
return true;
}
public boolean deposit(double amount) {
return true;
}
public static void main(String[] args) {
Account account = new Account();
account.transfer(11, 22, 33.33);
account.withdraw(44, 55.55);
account.transfer(66, 77, 88.88);
account.withdraw(99, 11.11);
// [error] The method getTransferCount() from the type Account is not visible
System.out.println(account.getTransferCount());
}
}
方面:
首先让我提到,我修复了您的代码中的两个错误:
仅当您正确绑定参数时,您的切入点才会匹配。 double amount
是两个方法参数中的第二个,而不是唯一一个。因此,您必须编写args(*, amount)
而不是args(amount)
您递增transferCount
之前来检查s.getTransferCount() == 0
,因此if
条件将永远不匹配。您想要的是s.getTransferCount() == 1
。
package de.scrum_master.aspect;
import de.scrum_master.app.Account;
public aspect LoggingAspect {
private int Account.transferCount = 0;
private int Account.getTransferCount() {
return transferCount;
}
pointcut firstTransfer(Account s, double amount) :
withincode(public void transfer (int, int, double)) &&
call(public boolean withdraw(int, double)) &&
target(s) &&
args(*, amount);
boolean around(Account s, double amount) : firstTransfer(s, amount) {
s.transferCount++;
if (s.getTransferCount() == 1) {
System.out.println("50% markup");
return s.deposit(amount * .5);
}
return false;
}
}
现在在Eclipse中,我看到了应用程序类中的编译错误,由于编译失败,方面本身也出现了后续问题。一旦注释掉main
方法的最后一行,它就会起作用。 (也许您必须重新保存方面或重新编译项目才能使弯曲的线条消失。)
实际上,最简单的方法是将getTransferCount()
设为公开而非私有。吸气剂通常是公共的,然后您也可以再次使用main
方法中的方法,程序输出将变为:
50% markup
2
BTW,在方面内,您无需使用getTransferCount()
。就像上面的行一样,您可以直接访问该字段。
更新:我答应过一个答案,为什么目标类无法通过ITD访问声明为private
的字段和方法:因为它们相对于方面而言是私有的]本身!此答案来自AspectJ维护人员本人,请阅读full answer here。