Что-то происходит в классе Account
, которым, к сожалению, вы здесь не поделились. Пожалуйста, узнайте, что такое MCVE и почему так важно всегда его предлагать. Особенно в контексте АОП это еще более важно, потому что аспект не имеет особого смысла без целевого класса. Я не могу отлаживать одно без другого, поэтому мне пришлось изобрести свой собственный фиктивный класс. Это на самом деле было бы вашей работой.
Возможно, вы пытаетесь использовать объявленные закрытые члены прямо из класса Account
. По причине, которую я пока не понимаю, это не работает, потому что он сбрасывает компилятор AspectJ с The method getTransferCount() from the type Account is not visible
или похожим сообщением об ошибке. Это должно быть ограничение или ошибка в 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());
}
}
Аспект:
Сначала позвольте мне упомянуть, что я исправил две ошибки в вашем коде:
Ваш pointcut будет соответствовать, только если вы правильно связали аргументы. 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()
publi c вместо private. Получатели обычно публикуются c, и вы также можете снова использовать метод из метода main
, и вывод программы будет следующим:
50% markup
2
Кстати, внутри аспекта, который вам не нужно использовать getTransferCount()
. Как и в приведенной выше строке, вы можете напрямую получить доступ к полю.
Обновление: Я обещал вам ответ на вопрос, почему целевой класс не может получить доступ к полям и методам, объявленным как private
через ITD: потому что они приватны относительно самого аспекта ! Этот ответ получен от самого сопровождающего AspectJ, пожалуйста, прочитайте полный ответ здесь .