Поле типа AspectJ не распознается в совете - PullRequest
1 голос
/ 25 апреля 2020

Я по сути пытаюсь отследить количество переводов для класса 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

1 Ответ

1 голос
/ 27 апреля 2020

Что-то происходит в классе 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, пожалуйста, прочитайте полный ответ здесь .

...