我想知道是否有办法确定触发此方面时激活的方法。我找到了返回源代码行的 JointPoint.getSourceLocation() 方法。我意识到我可以尝试解析该源文件并尝试从中确定方法……但似乎应该有更好的方法。
基本上,如果有以下代码:
class Monkey{
public void feed( Banana b ){
b.eat()
}
}
class Banana{
private static int bananaIdGen;
public final int bananaId = ++bananaIdGen;
private boolean eaten = false;
public void eat(){
if( eaten )
throw IllegalStateException( "Already eaten." );
else
eaten = true;
}
}
我想要一个像这样的方面
@After("call(void Banana.eat()) && target(bbb)")
public void whereEaten( Banana bbb ){
....
}
我可以在正文的哪个位置打印出诸如“Banana 47 eaten by org.example.Monkey(org.example.Banana)”之类的内容。
原因是如果一个方法被一个没有特定注释的方法调用,我想抛出一个错误。为此,我需要方法的方法。
最佳答案
我想 this question其 thisEnclosingJoinPointStaticPart
可以帮助您。
但解决问题的最佳方法是使用 withincode
和 call
切入点构建正确的连接点,如示例 here (参见契约(Contract)执行
部分)。这样您就可以防止调用带有或不带有某些注释的方法。
切入点列表可用here .
你的示例代码如何让我们引入注解:
package com.riapriority.test;
public @interface CanEat {
}
我们的 Banana
类:
package com.riapriority.test;
public class Banana {
private static int bananaIdGen;
private final int bananaId = ++bananaIdGen;
private boolean eaten = false;
public void eat() {
if (eaten)
throw new IllegalStateException("Already eaten.");
else
eaten = true;
}
public int getBananaId() {
return bananaId;
}
}
我们的 Monkey
类带有相应的注解:
package com.riapriority.test;
public class Monkey {
@CanEat
public void feed(Banana b) {
b.eat();
}
}
我们的 Airplane
类当然不能吃,所以没有 @CanEat
注释:
package com.riapriority.test;
public class Airplane {
public void feed(Banana b) {
b.eat();
}
}
我们用于测试的简单主类:
package com.riapriority.test;
public class WithincodeTest {
public static void main(String[] args) {
Banana monkeyBanana = new Banana();
Monkey monkey = new Monkey();
monkey.feed(monkeyBanana);
try {
monkey.feed(monkeyBanana);
} catch (IllegalStateException e) {
System.out.println(e.getMessage());
}
Banana airplaneBanana = new Banana();
Airplane airplane = new Airplane();
try {
airplane.feed(airplaneBanana);
} catch (IllegalStateException e) {
System.out.println(e.getMessage());
}
}
}
所以我们需要避免在飞机上吃香蕉。以及获得这个的相应方面:
package com.riapriority.test;
import java.text.MessageFormat;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class EatingAspect {
@Pointcut("call(void Banana.eat()) && target(banana)")
public void eatCall(Banana banana) {
}
@Pointcut("@withincode(CanEat)")
public void canEat() {
}
@AfterReturning("eatCall(banana) && canEat()")
public void whereEaten(Banana banana,
JoinPoint.EnclosingStaticPart thisEnclosingStaticPart) {
System.out.println(MessageFormat.format("Banana {0} eaten by {1}", banana.getBananaId(),
thisEnclosingStaticPart.getSignature()));
}
@Before("eatCall(banana) && !canEat()")
public void forbidEating(Banana banana,
JoinPoint.EnclosingStaticPart thisEnclosingStaticPart) {
throw new IllegalStateException(MessageFormat.format("Can''t eat {0} by {1}", banana.getBananaId(),
thisEnclosingStaticPart.getSignature()));
}
}
现在我们的测试主类产生了正确的输出:
Banana 1 eaten by void com.riapriority.test.Monkey.feed(Banana)
Already eaten.
Can't eat 2 by void com.riapriority.test.Airplane.feed(Banana)
希望这能解决您的问题。
关于java - 确定哪个方法触发了一个方面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5669768/