1. gzyueqian
      13352868059
      首頁 > 新聞中心 > > 正文

      在Eclipse RCP中實現控制反轉(IoC)

      更新時間: 2007-12-28 09:40:28來源: 粵嵌教育瀏覽量:1063

        這篇文章描述了在Eclipse RCP中引入依賴注射機制的一個簡單方法。為了避免污染Eclipse平臺的基礎設施并且透明的為RCP添加IoC框架,我們使用了動態字節碼操作(使用ObjectWeb ASM類庫),Java類加載agent以及Java標注技術的組合。

        Eclipse胖客戶端平臺(Rich Client Platform,RCP)是一個功能強大的軟件基礎(software foundation),它基于相互聯系并協作的插件,允許開發人員創建通用的應用程序。RCP使得開發人員可以更加關注應用程序的業務邏輯而不是花大量時間來重新發明輪子去編寫大量的應用程序管理邏輯。

        控制翻轉(IOC)和依賴注射是一種減少程序耦合性的設計模式。它們遵循了一個簡單的原則:你不必自己創建對象,你只需要描述如何創建對象。你不必去實例化或者定位你的組件需要的服務,你只需要去描述哪個組件需要哪個服務,其他組件(通常是容器)來負責將它組裝好。這也就是的好萊塢原則:不要打電話給我們,我們會打給你。

        這篇文章描述了在Eclipse RCP中引入依賴注射機制的一個簡單方法。為了避免污染Eclipse平臺的基礎設施并且透明的為RCP添加IoC框架,我們使用了動態字節碼操作(使用ObjectWeb ASM類庫),Java類加載agent以及Java標注技術的組合。

        什么是Eclipse胖客戶端平臺?

        簡單來說,Eclipse胖客戶端平臺是一組類庫,軟件框架以及運行環境,它可以用來創建獨立運行并且經常需要與網絡交互的應用程序。

        盡管Eclipse是作為一個集成開發環境(IDE)框架設計的,但是,從3.0版本開始,整個項目已經被重構成各種獨立的組件,以便于可以使用這些組件的一個子集來構建任意的應用程序。這個子集構成了RCP,它包含以下幾種組件:基本運行環境,用戶接口組件(SWT和JFace),插件以及OSGi層。圖1展示了Eclipse平臺的主要組件。

        整個Eclipse平臺是基于插件和擴展點(extensions points)這樣一個關鍵概念的。一個插件是可以獨立開發和發布的功能的小單元。它一般會打包成一個jar文件并且通過增加功能來擴充Eclipse平臺(例如,增加一個編輯器,工具欄按鈕或者一個編譯器)。整個平臺就是一組互相聯系并通訊的一組插件的集合。一個擴展點是一個已經存在的互相聯系的端點,可以被其他插件用來添加功能(功能:在Eclipse術語中叫做擴展)。擴展和擴展點通過XML配置文件定義并綁定在插件中。

        盡管插件已經使用了關注點分離這樣一個重要的模式,但是插件之間的強相互聯系和通訊會導致他們之間的強依賴關系。一個典型的例子就是需要定位應用程序需要的各種單例(Singleton)服務,例如數據庫連接池,日志處理器,或者用戶偏愛(preference)的設置信息的保存等。控制反轉和依賴注射是消除這些依賴的可行解決方案。

        控制反轉和依賴注射

        +控制反轉是一種設計模式,它主要關注如何將服務(或者應用程序組件)的定義和服務如何定位它們依賴的服務進行分離。為了完成這種分離,一般都會依賴一個容器,或者定位框架(locator framework),維護現存服務的列表+提供一種方法來將組件和它們依賴的服務綁定在一起。

        +提供一種方法讓應用程序代碼可以請求一個已經配置好的對象(例如,一個所有依賴都已經滿足的對象),這樣就可以保證該對象所有相關的服務都已經可用了。

        現存的框架一般都使用下面三種基本技術的組合來綁定服務和組件:

        +類型一(基于接口):服務對象需要實現一個專門的接口,這個接口為這些服務對象提供了一個對象,服務可以通過這個對象來查詢它們的依賴。這是一些早期的容器使用的模式,例如Excalibur. +類型二(基于setter):通過JavaBean屬性的setter方法將依賴的服務賦值給服務對象。HiveMind和Spring都是通過這種方式來實現的。

        +類型三(基于構造函數):依賴的服務通過構造函數的參數提供(不通過JavaBean屬性暴露)。這是PicoContainer使用的方式。HiveMind和Spring也使用了這種方式。

        我們將采用第二種方式的變種,通過帶標注的方法來提供服務。(示例應用的源代碼在資源中可以找到)。聲明依賴可以采用以下方式:

        @Injected public void aServicingMethod( Service s1, AnotherService s2) { // save s1 and s2 into class variables // to use them when needed}

        控制反轉容器會查找Injected標注并且使用需要的參數來調用這個方法。在我們為Eclipse平臺引入IoC的過程中,在服務和可服務對象間建立綁定關系的代碼被封裝在一個Eclipse插件中。這個插件定義了一個擴展點(com.onjava.servicelocator.servicefactory),用來為應用程序提供服務工廠。當一個可服務對象需要配置時,插件會向工廠請求服務的實例。正如下面的代碼,ServiceLocator類將會完成所有的工作。(我們會跳過那些處理擴展點解析的代碼,因為這些代碼會很簡單)

        /** * Injects the requested dependencies into the * parameter object. It scans the serviceable * object looking for methods tagged with the * {@link Injected} annotation.Parameter types are * extracted from the matching method. An  instance * of each type is created from the registered * factories (see {@link IServiceFactory})。 When * instances for all the parameter types have been * created the method is invoked and the next one * is examined. * * @param serviceable the object to be serviced * @throws ServiceException */

        public static void service(Object serviceable) throws ServiceException {

        ServiceLocator sl = getInstance();
        if (sl.isAlreadyServiced(serviceable)) {
        // prevent multiple initializations due to
        // constructor hierarchies
        System.out.println( "Object " + serviceable + " has already been configured ");
        return; }
        System.out.println("Configuring " + serviceable);
        // Parse the class for the requested services
        for (Method m : serviceable.getClass()。getMethods()) {
        boolean skip=false;
        Injected ann=m.getAnnotation(Injected.class)
        ; if (ann != null) {
        Object[] services = new Object[m.getParameterTypes()。length];
        int i = 0;
        for(Class<?> klass :m.getParameterTypes()){
        IServiceFactory factory = sl.getFactory(klass,ann.optional());
        if (factory == null) {
        skip = true;
        break; }
        Object service = factory.getServiceInstance();
        // sanity check: verify that the returned
        // service's class is the expected one
        // from the method
        assert(service.getClass()。equals(klass) || klass.isAssignableFrom(service.getClass()));
        services[i++] = service ; }
        try {
        if (!skip)
        m.invoke(serviceable, services); }
        catch(IllegalAccessException iae) {
        if (!ann.optional())
        throw new ServiceException( "Unable to initialize services on " + serviceable + ": " + iae.getMessage(),  iae); }
        catch(InvocationTargetException ite) {
        if (!ann.optional())
        throw new ServiceException( "Unable to initialize services on " + serviceable + ": " + ite.getMessage(),ite); } } }
        sl.setAsServiced(serviceable);}

        既然這個服務工廠返回的服務同樣可以是一個可服務對象,這個策略允許定義一種服務層次(但是,目前并不提供對循環依賴的支持)。

      免費預約試聽課

      亚洲另类欧美综合久久图片区_亚洲中文字幕日产无码2020_欧美日本一区二区三区桃色视频_亚洲AⅤ天堂一区二区三区

      
      

      1. 日本全部一级视频 | 日本在线高清不卡免费播放 | 中文字幕乱妇免费视频 | 视频一区手机视频 | 在线免费看片a | 日本最新一区二区三区在线 |