Как реализовать шаблон Wormhole с AspectJ (cflow)

Я пытаюсь разработать простую червоточину, используя AspectJ и cflow.

У меня есть два объекта значения Person и Account, как показано ниже

УЧЕТНАЯ ЗАПИСЬ

public class Account {

    private final String sortCode;
    private final String accountNumber;
    private final int balance;

    public Account(String sortCode, String accountNumber, int balance) {
        this.sortCode = sortCode;
        this.accountNumber = accountNumber;
        this.balance = balance;
    }

    public String getSortCode() {
        return sortCode;
    }

    public String getAccountNumber() {
        return accountNumber;
    }

    public int getBalance() {
        return balance;
    }

    @Override
    public String toString() {
        return "Account{" +
                "sortCode='" + sortCode + '\'' +
                ", accountNumber='" + accountNumber + '\'' +
                ", balance=" + balance +
                '}';
    }
}

ЧЕЛОВЕК

public class Person {

    private final String name;
    private final String address;
    private final int age;

    public Person(String name, String address, int age) {
        this.name = name;
        this.address = address;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public String getAddress() {
        return address;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                ", age=" + age +
                '}';
    }
}

И три "Слоя"

Слой А

public class Layer_A {

    public void doSomeLevelAprocess(Person person){

        System.out.println("doSomeLevelAprocess person " + person);
        new Layer_B().doSomeLevelBprocess();

    }
}

Слой Б

public class Layer_B {

    public void doSomeLevelBprocess(){

        System.out.println("doSomeLevelBprocess");
        new Layer_C().doSomeLevelCprocess(new Account("123456", "87654321", 1001));

    }
}

Слой C

public class Layer_C {

    public void doSomeLevelCprocess(Account account){

        System.out.println("doSomeLevelCprocess " );

    }
}

Я хотел бы иметь Person объект, который передается Layer_A методdoSomeLevelAprocess сделан доступным в Layer_C метод doSomeLevelCprocess

Это возможно?

мой аспект выглядит так

public aspect WormWhole {

    pointcut callerSpace(Person person): execution(* Layer_A.*(..)) && this(person);

    pointcut calleeSpace(Account account): this(account) && execution(public * Layer_C.*(..));

    pointcut wormhole(Person person, Account account):
            cflow(callerSpace(person)) && calleeSpace(account);

    before(Person person, Account account):
            wormhole(person, account){ **//WHAT DO I DO HERE?????** }
}

Правильно ли я выбрал pointcuts callerSpace и calleeSpace?

Какая логика требуется в

before(Person person, Account account):
                wormhole(person, account){ **//WHAT DO I DO HERE?????** }

ОБНОВИТЬ

Вопрос "Возможный дубликат" на самом деле не иллюстрирует, КАК достичь червоточины, он просто показывает "шаблон" для червоточины AspectJ. Кроме того, ответ на вопрос, о котором идет речь, не пытается пропустить контекст через несколько слоев, что является целой точкой червоточины.

ОБНОВИТЬ

Когда я изменю совет на это:-

public aspect WormWhole {

    pointcut callerSpace(Person person): execution(* Layer_A.*(..)) && this(person);

    pointcut calleeSpace(Account account): this(account) && execution(public * Layer_C.*(..));

    pointcut wormhole(Person person, Account account):
            cflow(callerSpace(person)) && calleeSpace(account);

    before(Person person, Account account):
            wormhole(person, account){
        System.out.println("Wormhole - " + person);
        System.out.println("Wormhole - " + account);


    }
}

Я получаю этот вывод:-

doSomeLevelAprocess person Person{name='aaa', address='aaa', age=19}
doSomeLevelBprocess
doSomeLevelCprocess 

Process finished with exit code 0

Это доказывает, что мои баллы не верны (я верю), но почему????

ОБНОВИТЬ

Я добавил в простой pointcut, который отлично работает

public aspect WormWhole {

    pointcut callSayHello(): call(* Layer_A.*(..)) || call(* Layer_B.*(..)) || call(* Layer_C.*(..))  ;

    pointcut callerSpace(Person person): execution(* Layer_A.*(..)) && this(person);

    pointcut calleeSpace(Account account): this(account) && execution(public * Layer_C.*(..));

    pointcut wormhole(Person person, Account account):
            cflow(callerSpace(person)) && calleeSpace(account);

    before(Person person, Account account):
            wormhole(person, account){
        System.out.println("Wormhole - " + person);
        System.out.println("Wormhole - " + account);


    }

    after() : callSayHello()  {
        System.out.println("After call sayHello" + thisJoinPoint);
    }
}

Выход из выполнения теста

doSomeLevelAprocess person aaa
doSomeLevelBprocess
doSomeLevelCprocess account 87654321
After call sayHellocall(void Layer_C.doSomeLevelCprocess(Account))
After call sayHellocall(void Layer_B.doSomeLevelBprocess())
After call sayHellocall(void Layer_A.doSomeLevelAprocess(Person))

Process finished with exit code 0

Я использую CTW в IntelliJ 14.1.14, с aspectjrt-1.8.6.jar

1 ответ

Решение

Вы правы, у вас что-то не так с вашими pointcuts, поэтому компилятор AspectJ показывает это предупреждение:

advice defined in Wormhole has not been applied [Xlint:adviceDidNotMatch]   

Причина проста: вы пытаетесь связать аргументы вашего метода через this() вместо args(), Таким образом, обе точки не могут совпадать, потому что this объекты в двух контекстах выполнения являются экземплярами Layer_A а также Layer_Cне Person а также Account,

Это небольшое изменение исправляет ваш аспект червоточины:

pointcut callerSpace(Person person) :
    execution(* Layer_A.*(..)) && args(person);

pointcut calleeSpace(Account account) : 
    execution(public * Layer_C.*(..)) && args(account);
Другие вопросы по тегам