2014-04-27 99 views
8

確定這個問題從來沒有被問過在網絡上,所以在這裏: 我正在學習Java(初學者 - 中級水平),並且我決定嘗試使用面向方面的編程繼續上課。面向方面編程在Java中沒有AspectJ?

現在這個東西應該很容易學習(至少這是網絡共識) 如此之多以至於「方面」被認爲是標準類的稍微修改版本,所以我的問題是:如果方面基本上都是類,

爲什麼我們必須安裝AspectJ才能在Java中執行AOP?

因爲這只是增加了一層額外的複雜性,使得概念更難掌握。

我想要的是能夠在不使用AspectJ(或任何其他附加組件)的情況下編寫一個方面,換句話說,我想只使用BASIC Java &的標準Java類來執行AOP。是否有可能,如果是這樣,我該如何寫這些類?

+2

當然可以。你甚至不需要另一個框架(比如Spring AOP)。在時間的考驗中,AspectJ未能取得成功。例如,屬性+反射可以成爲框架AOP的一種方法。 –

+1

是一個很好的問題..我們可以編寫反射類型的代碼,並使用正則表達式來調用基於指令的方法,如之前,之後和周圍..我們可以解決它,但需要多一點時間.. –

+0

alrite謝謝你們。看起來像我有一個平行的方式去,因爲反思等(與內省有關)是暫時超出我的範圍。大聲笑 我想問問我的問題的另一種方式是,如何將一個(簡單的)AspectJ編碼的程序轉換爲一個純粹的純Java程序,儘可能少的修改? – user3578836

回答

3

Java不支持AOP開箱即用,我不建議您自己實現它,因爲您必須在加載時修改類文件。或者,您也可以修改合併的類文件,但這會更復雜。

AspectJ使用Java代理來設置編織類加載器(它可以在加載時修改類文件),但也可以手動使用自己的類加載器。如果您想要修改的類都實現了一個接口,那麼您可以使用Java Proxies作爲AOP。否則,你將不得不使用像CGLib,Javassist或ASM這樣的外部庫(或者學習Java字節碼是如何工作的)。

一些進一步的信息:

代理例如:

import java.lang.reflect.InvocationHandler; 
import java.lang.reflect.Method; 
import java.lang.reflect.Proxy; 

public class ProxyExample { 

    public static void main(String[] args) { 
     AnInterface obj = new AClass(); 
     AnInterface proxyObj = createProxy(obj); 
     System.out.println(obj.aMethod()); 
     System.out.println(proxyObj.aMethod()); 
    } 

    private static AnInterface createProxy(AnInterface obj) { 
     return (AnInterface) Proxy.newProxyInstance(ProxyExample.class.getClassLoader(), 
       new Class<?>[] {AnInterface.class}, 
       new InvocationHandler() { 
      @Override 
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
       return "proxy: " + method.invoke(obj); 
      } 
     }); 
    } 

    static interface AnInterface { 
     public String aMethod(); 
    } 

    static class AClass implements AnInterface { 
     @Override 
     public String aMethod() { 
      return "string"; 
     } 
    } 

} 
+0

好的thx!儘管java代理超出了我的能力atm(我知道的唯一「代理」是當我的web請求使用另一個IP時,隱藏我自己的IP。我不知道這兩個概念是相關的,因爲我見過這個詞「代理」在很多不同的領域使用,這是令人困惑的:/) – user3578836

+0

@ user3578836,我剛剛添加了一個代理示例。此上下文中的代理意味着可以將方法調用委託給另一個對象的對象。 –

6

AspectJ是一個缺乏更好的詞,「純」的方面框架。標準是它可以在各種情況下廣泛使用。任何方面,任何階層,任何時候。

也就是說,截取和包裝方法調用的方面技術,已經在Java中普遍找到了它的方式。然而,這些傾向於通用方面概念專用於特定目的。

早期的EJB功能已經完成了很早的「方面」。這需要使用XML文件來擴充類和接口,以便容器可以創建將方法調用包裝到事務上下文中的代理對象。這些方法的包裝是一個方面的概念,但早期的EJB規範只提供了特定事務管理用例的功能。

Java 1.5註釋的到來打開了面向方面編程的這種增強概念。這並不是說你需要註釋來啓用它,而只是讓框架更容易使用,因爲註釋消除了外部元數據配置(可能使用XML文件)。因此,現在許多Java系統使用面向方面編程的概念,通常通過反射和註釋來實現某些功能。這是否是實例注入,圍繞方法,驗證等。

它的關鍵組件是攔截方法調用的一些機制。 AspectJ通過即時改變目的地類而不是插入中間人來工作。 EJB的工作原理是在接口上創建代理(您可以在Java中開箱即可使用),然後當程序向容器請求實例時,它會提供由實際實例支持的代理。

因此,無論何時何地,爲了實現「通用」AOP,您當然需要AspectJ等廣泛的應用。但要獲得它的許多好處,你不需要走得太遠。一個簡單的工廠類和一個接口可以很容易地完成這項工作。