I was wondering if there is anyway of determining what method was active when this aspect was triggered. I found the method JointPoint.getSourceLocation() which returns the source code line. I realised I could try to parse that source file and try to determine the method from that... but there seems like there ought to be a better way.
Basically, if has the following code:
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;
}
}
I'd like to have an aspect like
@After("call(void Banana.eat()) && target(bbb)")
public void whereEaten( Banana bbb ){
....
}
Where in the body I could print out something like `"Banana 47 eaten by org.example.Monkey(org.example.Banana)".
The reason is that that I would like to throw an error if a method has been called by a method without a certain annotation on it. For that I'd need to have the Method of the m开发者_JAVA技巧ethod.
I suppose this question with its thisEnclosingJoinPointStaticPart
can help you.
But the best way to solve your problem is to construct the right join point using withincode
and call
pointcuts as in example here (see Contract Enforcement
section). This way you prevent calls from methods with or without certain annotation.
The list of pointcuts is available here.
What about your sample code lets introduce annotation:
package com.riapriority.test;
public @interface CanEat {
}
Our Banana
class:
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;
}
}
Our Monkey
class with corresponding annotation:
package com.riapriority.test;
public class Monkey {
@CanEat
public void feed(Banana b) {
b.eat();
}
}
Our Airplane
class which, of course, can't eat and so hasn't @CanEat
annotation:
package com.riapriority.test;
public class Airplane {
public void feed(Banana b) {
b.eat();
}
}
Our simple main class for testing:
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());
}
}
}
So we need to avoid eating bananas by Airplane. And the corresponding aspect to obtain this:
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()));
}
}
So now our test main class produces the right output:
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)
Hope this solves your problem.
精彩评论