我想知道在触发这个方面时是否还有确定哪种方法是活跃的。我找到了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 ){
....
}
在身体里我可以打印出类似“org.example.Monkey(org.example.Banana)吃过的香蕉47”。
原因是如果一个方法被一个没有特定注释的方法调用,我想抛出一个错误。为此,我需要有方法的方法。
答案 0 :(得分:2)
我认为this question及其thisEnclosingJoinPointStaticPart
可以帮助您。
但解决问题的最佳方法是使用withincode
和call
切入点构建正确的连接点,例如here(请参阅Contract Enforcement
部分)。这样就可以防止来自带或不带某些注释的方法的调用。
切入点列表可用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)
希望这能解决你的问题。