簡體   English   中英

建議中未識別 AspectJ 類型間字段

[英]AspectJ inter-type field not recognized in advice

我實際上是在嘗試跟蹤賬戶 class 的轉賬次數。 Reading the docs here: https://www.eclipse.org/aspectj/doc/released/progguide/language-anatomy.html And on slide 48 and 49 here: https://www.eclipse.org/aspectj/doc/發布/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;
        }
}

但是,如上面代碼中所述,這些字段不被識別為存在於方面內的 class 上。 我究竟做錯了什么?

我得到的錯誤是: transferCount cannot be resolved or is not a field

Account class 中發生了一些事情,很遺憾您沒有在這里分享。 請了解MCVE是什么,以及為什么始終提供 MCVE 如此有價值。 特別是在 AOP 的上下文中,它甚至更重要,因為如果沒有目標 class,方面就沒有多大意義。 我無法調試一個沒有另一個,這就是為什么我必須發明自己的虛擬 class。 那實際上是你的工作。

可能您正在嘗試直接從Account class 中使用聲明的私有成員。 由於我還不明白的原因,這不起作用,因為它使用The method getTransferCount() from the type Account is not visible或類似的錯誤消息拋出 AspectJ 編譯器。 這一定是 AspectJ 中的限制或錯誤,我會詢問維護者並稍后在這里報告。

但首先讓我們重現您的情況:

應用 class:

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());
  }
}

方面:

首先讓我提一下,我修復了您的代碼中的兩個錯誤:

  • 只有正確綁定 arguments 時,您的切入點才會匹配。 double amount是兩個方法參數中的第二個,而不是唯一一個。 因此你必須寫args(*, amount)而不是args(amount)

  • 在檢查s.getTransferCount() == 0之前增加transferCount ,因此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 中,我在應用程序 class 中看到編譯錯誤,並且由於編譯失敗導致方面本身的后續問題。 只要您注釋掉main方法的最后一行,它就可以工作。 (也許您必須重新保存方面或重新編譯項目才能使波浪線消失。)

實際上,最簡單的做法是讓getTransferCount()公開而不是私有。 Getter 通常是公共的,然后您也可以再次使用main方法中的方法,程序 output 將變為:

50% markup
2

順便說一句,在這方面您不需要使用getTransferCount() 就像上面的行一樣,您可以直接訪問該字段。


更新:我答應你回答為什么目標 class 不能訪問通過 ITD 聲明為private的字段和方法:因為它們相對於方面本身是私有的,這個答案來自 AspectJ 維護者本人,請閱讀完整答案在這里

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM