如何用AspectJ(cflow)实现虫洞模式

时间:2015-07-20 13:26:12

标签: java aspectj

我正在尝试使用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 +
                '}';
    }
}

PERSON

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 +
                '}';
    }
}

三个“图层”

第A层

public class Layer_A {

    public void doSomeLevelAprocess(Person person){

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

    }
}

第B层

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?????** }
}

我是否正确选择了切入点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

这证明我的切入点不正确(我相信),但为什么????

更新

我添加了简单的切入点,工作正常

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

我在IntelliJ 14.1.14内使用CTW,aspectjrt-1.8.6.jar

1 个答案:

答案 0 :(得分:1)

你是对的,你的切入点出了问题,这就是为什么AspectJ编译器会显示这个警告:

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

原因很简单:您试图通过this()而不是args()绑定方法参数。这样两个切入点都无法匹配,因为两个执行上下文中的this对象是Layer_ALayer_C的实例,而不是PersonAccount

这个小改动修复了你的虫洞模式方面:

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

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