2011-04-14 66 views
2

我想知道在觸發此方面時是否存在確定哪種方法處於活動狀態。我找到了返回源代碼行的方法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){ 
     .... 
} 

一個方面,凡在我身上可以打印出像吃了'「香蕉47事通過org.example.Monkey(org.example.Banana)「。

原因是我想拋出一個錯誤,如果一個方法被一個沒有特定註釋的方法調用。爲此,我需要有方法的方法。

+0

我已經添加了代碼示例,我想這可以解決您的問題。 – Constantiner 2011-04-15 15:18:29

回答

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) 

希望這能解決你的問題。