實現ClassLoaderDelegateHook控制Equinox的類加載

          Equinox的設計非常經典,其在擴展方面提供了很多的支持,同樣包括類加載方面的控制,除了通過標準的org.osgi.framework.bootdelegation以及equinox提供的osgi.parentClassLoader這兩個屬性來簡單的控制類加載之外,還可通過實現ClassLoaderDelegateHook來更為靈活的控制類加載。

          對Equinox代碼進行分析,想讓擴展的ClassLoaderDelegateHook起作用,首先要能夠讓這個ClassLoaderDelegateHook注冊到Equinox中,Equinox在進行類加載的過程中會調用searchHooks來尋找ClassLoaderDelegateHook的實現,尋找的方法為獲取bundle.framework.delegateHooks屬性,而framework中的delegateHooks屬性是在initialize時通過adaptor的getHookRegistry()的getClassLoaderDelegateHooks()方法來獲取的,并且framework沒有提供setDelegateHooks或addDelegateHook這樣的方法,所以沒辦法直接設置,從這來看,是否意味著只需要在framework initialize之前通過adaptor的getHookRegistry來注冊ClassLoaderDelegateHook就可以呢,繼續看BaseAdaptor類,恩,確實通過adaptor的getHookRegistry可以來增加ClassLoaderDelegateHook,但由于啟動過程是在EclipseStarter里面完成的,BaseAdaptor是在啟動的代碼里創建的,這樣就沒辦法保證在framework initialize之前增加自己實現的ClassLoaderDelegateHook了,查看EclipseStarter代碼,幸運的是可以通過設置osgi.adaptor屬性來指定Adaptor類的名稱,于是決定繼承BaseAdaptor,在構造器中創建通過獲取HookRegistry來增加自行實現的ClassLoaderDelegateHook類,這里還有個小問題,BaseAdaptor在構造器中創建HookRegistry后調用了其initiliaze方法,而HookRegistry在initialize方法中將其私有的一個readonly屬性設置為了true,這導致的后果是無法在這之后增加ClassLoaderDelegateHook,如增加,則會拋出:IllegalStateException,錯誤信息為:Cannot add hooks dynamically,因此,在調用addClassLoaderDelegateHook之前必須通過反射先將HookRegistry中的readonly屬性設置為false,按照上面的方法,實現的關鍵代碼如下:

          // 設置自行實現的Adaptor類名
          FrameworkProperties.setProperty(EclipseStarter.PROP_ADAPTOR, CustomAdaptor.class.getName());

          public class CustomAdaptor extends BaseAdaptor {

              
          public CustomAdaptor(String[] args) {
                  
          super(args);
                  HookRegistry hookRegistry
          =getHookRegistry();
                  
          try{
                      Field readOnlyField
          =HookRegistry.class.getDeclaredField("readonly");
                      readOnlyField.setAccessible(
          true);
                      readOnlyField.setBoolean(hookRegistry, 
          false);
                      hookRegistry.addClassLoaderDelegateHook(自行實現的ClassLoaderDelegateHook類);
                  }
                  
          catch(Exception e){
                      
          e.printStackTrace();
                  }
              }

          }

          ClassLoaderDelegateHook類則可根據自己的需求進行實現,在這個類中可靈活控制類加載的過程,接口中控制類加載的方法說明如下:
          preFindClass 
          在Equinox判斷是否需要從boot classloader中加載后,就會嘗試調用ClassLoaderDelegateHook的這個方法來加載類,如此方法拋出ClassNotFoundException,則終止類查找,因此,如果希望Hook中加載不到時繼續執行Equinox的類加載的話,在Hook中就不要拋出ClassNotFoundException。
          postFindClass
          在Equinox已經嘗試過從Bundle的import-package、require-bundle、bundle-classpath以及dynamicimport-package中加載后,會嘗試調用ClassLoaderDelegateHook的這個方法來加載類。

          上面的方法并不優雅,從Equinox設計了Hook來看,不可能要這么復雜才能增加一個Hook,于是繼續回頭看代碼,不負期望,在HookRegistry的initialize方法中,會去加載配置的osgi.hook.configurators、osgi.hook.configurators.include和osgi.hook.configurators.exclude三個屬性值或指定的hookconfigurators.properties文件,最后合并形成需要加載執行的HookConfigurator類,從上面的代碼來看,只用在自行實現的ClassLoaderDelegateHook類上再增加HookConfigurator接口的實現,并將其注冊到HookRegistry中,最后在osgi.hook.configurators中配置這個類即可,由于equinox內部已經有配置了一些HookConfigurator的,因此此處需要把equinox jar中的hookconfigurators.properties里面配置的hook.configurators也增加進去,要么就是把自己需要增加的HookConfigurator加到equinox jar的hookconfigurators.properties中,這種方法就優雅很多了,按照這種方法實現后的關鍵代碼如下:

          // 設置需要裝載的HookConfigurator的實現類
          FrameworkProperties.setProperty("osgi.hook.configurators", CustomClassLoaderDelegate.class.getName());

          public class CustomClassLoaderDelegate implements ClassLoaderDelegateHook,HookConfigurator {

              
          public Class postFindClass(String name, BundleClassLoader classloader,
                      BundleData data) 
          throws ClassNotFoundException {
                  
          // 自行實現
              }
              

              
          public URL preFindResource(String name, BundleClassLoader classloader,
                      BundleData data) 
          throws FileNotFoundException {
                  
          // 自行實現
              }

              
          public Enumeration preFindResources(String name, BundleClassLoader classloader,
                      BundleData data) 
          throws FileNotFoundException {
                  
          // 自行實現
              }

              
          public String postFindLibrary(String arg0, BundleClassLoader arg1,
                      BundleData arg2) {
                  
          // 自行實現
              }

              
          public URL postFindResource(String arg0, BundleClassLoader arg1,
                      BundleData arg2) 
          throws FileNotFoundException {
                  
          // 自行實現
              }

              
          public Enumeration postFindResources(String arg0, BundleClassLoader arg1,
                      BundleData arg2) 
          throws FileNotFoundException {
                  
          // 自行實現
              }

              
          public Class preFindClass(String arg0, BundleClassLoader arg1,
                      BundleData arg2) 
          throws ClassNotFoundException {
                  
          // 自行實現
              }

              
          public String preFindLibrary(String arg0, BundleClassLoader arg1,
                      BundleData arg2) 
          throws FileNotFoundException {
                  
          // 自行實現
              }

              
          public void addHooks(HookRegistry registry) {
                  registry.addClassLoaderDelegateHook(
          this);
              }

          }

          ps: 在《OSGi原理與最佳實踐》中沒來得及寫上這部分,就在這篇blog上寫了。

          posted on 2009-07-14 11:04 BlueDavy 閱讀(6160) 評論(1)  編輯  收藏 所屬分類: OSGi、SOA、SCA

          評論

          # re: 實現ClassLoaderDelegateHook控制Equinox的類加載 2015-10-02 23:37 衡蕪公爵

          親,你可以通過一個文件注冊進去奧~~  回復  更多評論   

          公告

           









          feedsky
          抓蝦
          google reader
          鮮果

          導航

          <2009年7月>
          2829301234
          567891011
          12131415161718
          19202122232425
          2627282930311
          2345678

          統計

          隨筆分類

          隨筆檔案

          文章檔案

          Blogger's

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 德保县| 汽车| 北海市| 克东县| 呼伦贝尔市| 无棣县| 汽车| 丹凤县| 岑巩县| 伽师县| 凭祥市| 贵德县| 福泉市| 珠海市| 班戈县| 鲁甸县| 东乌珠穆沁旗| 揭东县| 柯坪县| 塔城市| 汾阳市| 华亭县| 高尔夫| 五河县| 淅川县| 海安县| 宜黄县| 上犹县| 孟津县| 德阳市| 泸水县| 普定县| 新兴县| 伊川县| 太原市| 黄平县| 西安市| 广德县| 炉霍县| 禹城市| 囊谦县|