java - 确定哪个方法触发了一个方面

标签 java aspectj

我想知道是否有办法确定触发此方面时激活的方法。我找到了返回源代码行的 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 questionthisEnclosingJoinPointStaticPart 可以帮助您。

但解决问题的最佳方法是使用 withincodecall 切入点构建正确的连接点,如示例 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/

相关文章:

Java新字段getter null

java - 如何处理 Selenium WebDriver 中的间歇性警报?

JavaFX 事件过滤器实现

android - 是否可以在 Android Studio 项目中集成 Dagger 和 AspectJ?

java - Spring 4 AOP方面从未被调用?

java - AspectJ 和 Spring AOC

java - 使用 Maven AspectJ 编织依赖项时重复类

java - 底部表格不适用于谷歌地图

java - 无法从 jar 文件访问 xsl 文件 (Mule)

spring - 如何在Grails 3.3.2中为领域类保存方法创建方面?