2012-08-26 34 views
4

我正在尋找一個使用AspectJ實現蟲洞模式實現的示例(如果Guice AOP有權實現此操作,會感興趣)。使用AspectJ實現蟲洞圖案

蠕蟲孔基本上可以讓你沿着例如呼叫流程傳遞附加參數:

// say we have 
class foo { 
    public int m0 int a, int b) { 
    return m1(a,b); 
    } 

    public int m1 int a, int b) { 
    return m2(a,b); 
    } 

    public int m2 int a, int b) { 
    return a+b; 
    } 
} 
// and I wanted in a non-invasive manner to pass a third parameter of type 
class context { 
    String userName; 
    long timeCalled; 
    String path; 
} 
// I could use an advise to say print the context information 
// to trace what was going on without mucking up my method signatures 

我相信這拉姆尼瓦斯·拉達在他的行動書的AspectJ這樣一個例子。

在此先感謝。

回答

4

事實上,在AspectJ in Action中有一個例子。如果您查看table of contents,您會注意到第12.2章是您正在查找的內容。購買這本書是個好主意。我可以熱烈推薦它。因爲我不知道這是否是好的,把剛纔複製的書&粘貼部位,我只是在這裏引用的模板:

public aspect WormholeAspect { 
    pointcut callerSpace(<caller context>) : 
     <caller pointcut>; 

    pointcut calleeSpace(<callee context>) : 
     <callee pointcut>; 

    pointcut wormhole(<caller context>, <callee context>) : 
     cflow(callerSpace(<caller context>)) && 
     calleeSpace(<callee context>); 

    // advice to wormhole 
    before(<caller context>, <callee context>) : 
     wormhole(<caller context>, <callee context>) 
    { 
      ... advice body 
    } 
} 

有上TheServerSide.com老article by Laddad有更具體的例子。這本書不一樣,但相似。

正如你所看到的,在AspectJ中很容易做,因爲你有cflow()切入點。我從未使用過Guice,但其AOP introduction頁面提到它們的實現是AOP Alliance規範的一部分。看看AOP Alliance API,沒有什麼東西看起來像是一個cflow()切入點,它是圍繞構造函數&方法調用加上字段訪問。

那麼如果你想避免通過所有圖層傳遞參數,你可以在Spring(沒有AspectJ)或Guice中做什麼?顯而易見的解決方案是由調用者聲明和管理(即分配,但也清除)變量的ThreadLocal變量,並由被調用者訪問。這不好,只是一個解決方法,以免臃腫的API。但它要求調用者和被調用者對他們想要共享什麼以及如何共同理解。在某種程度上,這種實現更多的是反模式而不是模式。如果可以的話,使用AspectJ以便以一種乾淨和模塊化的方式解決這個問題,將需要解決的問題封裝在一個模塊(方面)中。

+0

千恩萬謝@kriegaex ......我會拿起書 – user1172468

1

不要使用蟲孔模式......實際上,只有在確定需要使用AOP的情況下才能使用AOP,否則請保留它。

蟲洞模式的缺點是你跳過很多層......是你真正想要的嗎? :)

Grtz,

克里斯托夫

+0

^h我,所以我喜歡使用蟲洞模式來保持我的方法簽名清潔。例如,如果我想在我的調用流程中傳遞大量的上下文和其他信息,這純粹是實現的副作用,並且與手頭的用例無關。 – user1172468

1

一個簡單的例子。想象一下,你有背景目標對象提供的功能,這在某種程度上依賴於上下文的狀態:

class T { 
    public void foo() { 
     System.out.println("T.foo()"); 
    } 
} 

class Context { 
    public boolean isValid = true; 
    public void doStuff() { 
     T t = new T(); 
     t.foo(); 
    } 
} 

public class Main { 
    public static void main(String[] args) { 
     Context c = new Context(); 
     c.doStuff(); 
    } 
} 

這將確保Context該實例的方面可以對T實例只有當調用foo()成員isValid設置爲true可以看看下面的方法:

public aspect ContextStateValidation { 

    pointcut MyContext(Context c) : 
     execution(* Context.*()) && this(c); 

    pointcut FooCalls(T t) : 
     call(* T.foo()) && target(t); 

    pointcut FooCallsInMyContext(Context c, T t) : 
     cflow(MyContext(c)) && FooCalls(t); 

    void around(Context c, T t) : FooCallsInMyContext(c, t) { 
     if (c.isValid) 
      proceed(c, t); 
    } 
}