如何使用 AspectJ (cflow) 实现虫洞模式
How to implement Wormhole pattern with 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 +
'}';
}
}
还有三个"Layers"
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?????** }
更新
"Possible Duplicate" 问题实际上并没有说明如何实现虫洞,它只是显示了 AspectJ 虫洞的 "template"。另外提到的问题答案不试图通过多层传递上下文,这是虫洞的全部意义。
更新
当我将建议更改为:-
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
你是对的,你的切入点有问题,这就是 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);
我正在尝试使用 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 +
'}';
}
}
还有三个"Layers"
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?????** }
更新
"Possible Duplicate" 问题实际上并没有说明如何实现虫洞,它只是显示了 AspectJ 虫洞的 "template"。另外提到的问题答案不试图通过多层传递上下文,这是虫洞的全部意义。
更新
当我将建议更改为:-
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
你是对的,你的切入点有问题,这就是 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);