<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Live a simple life

    沉默(zhu_xing@live.cn)
    隨筆 - 48, 文章 - 0, 評論 - 132, 引用 - 0
    數據加載中……

    【Eclipse插件開發】Java基本類加載原理 VS 插件類加載原理

                標題說明了一切,我想說的就是如果你在做Eclipse插件開發,想真正搞清楚Eclipse插件類加載,那么Java基本類加載原理是基礎,無法逾越?。?!我會舉一個小例子來簡單說明一下
                
            【情景】
              例如我們在底層模塊插件(就叫做Host)中做了一個解析器實現(什么解析器就別管了),對應類型為IParser(com.my.host.parser.IParser),簡單定義如下:
    1 public interface IParser {
    2     public Object parse(Object input) throws CoreException;
    3 }
             
            基本的原則告訴我們:如果一個實例的創建過程較為負責,則因該把這種實例的創建和實例的使用解耦合。于是,我們在Host插件中提供了一個如下的工廠類:
     1 public class ParserFactory {
     2     /**
     3      * create IParser instance
     4      * 
     5      * @param clazz  qualified parser type name
     6      * @return
     7      * @throws CoreException
     8      */
     9     public static IParser createParser(String clazz) throws CoreException{
    10         try {
    11             Object object = Class.forName(clazz).newInstance();
    12             if (object instanceof IParser)
    13                 return (IParser)object;
    14             
    15             return null;
    16         } catch (Exception e) {
    17             throw new CoreException(new Status(IStatus.ERROR, "host"101"創建工廠失敗:" + clazz, e));
    18         }
    19     }
    20     
    21     /**
    22      * create IParser instance with corresponding class loader
    23      * 
    24      * @param clazz         qualified parser type name
    25      * @param classLoader   corresponding class loader
    26      * @return
    27      * @throws CoreException
    28      */
    29     public static IParser createParser(String clazz, ClassLoader classLoader) throws CoreException{
    30         try {
    31             Object object = classLoader.loadClass(clazz);
    32             if (object instanceof IParser)
    33                 return (IParser)object;
    34             
    35             return null;
    36         } catch (Exception e) {
    37             throw new CoreException(new Status(IStatus.ERROR, "host"101"創建工廠失?。?/span>" + clazz, e));
    38         }
    39     }
    40 }
    41 
            這里的簡單工廠中創建方法返回的是IParser接口類型,目的就是為了保證可以創建子類型的靈活性,同時確保對外提供的接口是一致的,有助于客戶端基于接口編程(說的有點上綱上線了~_~)

            同時我們在Host插件中,也提供了一個默認的IParser實現,就叫做DefaultParser吧。那到這里我們的Host插件共提供了如下類型:
            com.my.host.parser.IParser                     解析器接口定義
            com.my.host.parser.ParserFactory          解析器工廠
            com.my.host.parser.impl.DefaultParser    解析器接口默認實現

            下面我們在Host插件的基礎之上建立了上層功能插件(就叫做Extension插件吧,Extension插件依賴于Host插件),提供了解析器實現,對應類型為com.my.extension.parser.MyParserImpl。我們在Extension插件中想使用這個實現,假設有如下幾種中創建方式:
    第一種:直接創建實例,偏不用你Host中的工廠。 俗了點,但是沒問題。
     1 package com.my.extension.model;
     2 
     3 public class Customer {
     4     public void doOperation(Object input) throws CoreException{
     5         //直接創建實例的方式
     6         IParser parser = new MyParserImpl();
     7         
     8         Object model = parser.parse(input);
     9         //TODO 拿到模型之后干其他活
    10     }
    11 }

    第二種,直接使用Class.forName(),還是不用你Host中的工廠。也是俗了點,但也沒問題,為什么沒問題,可能就沒有想清楚了~_~
     1 package com.my.extension.model;
     2 
     3 public class Customer {
     4     public void doOperation(Object input) throws CoreException{
     5         try {
     6             //使用默認的Class.forName()的方式
     7             IParser parser = (IParser)Class.forName("com.my.extension.parser.MyParserImpl").newInstance();
     8             
     9             Object model = parser.parse(input);
    10             //TODO 拿到模型之后干其他活
    11         } catch (Exception e) {
    12             // TODO: handle exception
    13         }
    14         
    15     }
    16 }

    第三種:用一把工廠 ---》》ClassNotFoundException
     1 package com.my.extension.model;
     2 
     3 public class Customer {
     4     public void doOperation(Object input) throws CoreException{
     5         //使用工廠,不指定類加載器
     6         IParser parser = ParserFactory.createParser("com.my.extension.parser.MyParserImpl");
     7         
     8         Object model = parser.parse(input);
     9         //TODO 拿到模型之后干其他活
    10     }
    11 }
    疑惑了:第二種使用方式為什么沒問題,第三種怎么就有問題了?代碼實現中都是Class.forName("").newInstance();調用?。???

    大致錯誤原因:
            這個時候如果你只基本熟悉Eclipse的插件類加載機制(會去找所依賴的插件中的類型...),可能一時半會想不清楚。Java的類加載基本原理中有一條:Class.forName()調用方式加載類型所默認使用的類加載器實例是加載當前類型的類加載器。對于在Extension插件Customer中調用Class.forName()使用的是加載Customer類型的類加載器,也就是Extension插件的唯一類加載器;對于在Host插件中的ParserFactory中調用Class.forName()則使用的加載ParserFactory類型的類加載器實例,也就是Host插件的唯一類加載器。你想讓Host插件類加載器去加載一個在Extension插件中定義的類型,注意Extension插件是依賴于Host插件的啊,根據Eclipse插件類記載規則,這種加載請求無法從Host插件類加載器委托到Extension類加載器(說明:使用擴展點機制可以,extension registry會幫你委托這一個請求,找到對應的BundleHost...)。如果你想讓Extension插件的類加載器去加載Host中定義的切export出來的類型,Extension插件的類加載器會把這個請求合理的委托給Host插件類加載器。


    第四種:用一把工廠,指定類加載器。由于com.my.extension.parser.MyParserImpl本身就和Customer定義在同一插件中,所以公用同一插件類加載器實例,兩者對于Extension插件來說都是local class,加載肯定沒問題。
     1 package com.my.extension.model;
     2 
     3 public class Customer {
     4     public void doOperation(Object input) throws CoreException{
     5         //使用工廠,指定類加載器
     6         IParser parser = ParserFactory.createParser("com.my.extension.parser.MyParserImpl"this.getClass().getClassLoader());
     7         
     8         Object model = parser.parse(input);
     9         //TODO 拿到模型之后干其他活
    10     }
    11 }

    以上是舉了一個小例子,僅僅是為了說明一個道理:掌握Java類加載基本原理是掌握Eclipse插件類加載原理的基礎,不可逾越?。?!如果讓你在一個插件應用中寫一個較為負責的自定義類加載器,但靠背一點Eclipse類加載的規則,那更不夠了...

    Java類加載基本原理還有很多,我博客中有隨筆(老早之前寫的,土了點,頭一段時間貼到了博客上了)。


    本博客中的所有文章、隨筆除了標題中含有引用或者轉載字樣的,其他均為原創。轉載請注明出處,謝謝!

    posted on 2008-08-28 15:32 zhuxing 閱讀(3615) 評論(0)  編輯  收藏 所屬分類: Eclipse Plug-in & OSGI

    主站蜘蛛池模板: 一级特黄a大片免费| 久久久久亚洲av毛片大| 国产精品免费一区二区三区四区| 亚洲精品亚洲人成在线| 亚洲电影中文字幕| 亚洲人成网站在线观看播放| 国产传媒在线观看视频免费观看| 国产成人免费午夜在线观看| a级日本高清免费看| 猫咪www免费人成网站| 亚洲精品乱码久久久久蜜桃| 亚洲1区1区3区4区产品乱码芒果| 亚洲成人免费在线| 亚洲国产精品一区第二页| 亚洲伊人久久综合影院| 国产成人一区二区三区免费视频| 国产成人A在线观看视频免费| 亚洲免费视频网址| 1000部夫妻午夜免费| 男人都懂www深夜免费网站| 久久久久久国产a免费观看不卡| 免费的黄网站男人的天堂| 国产精品亚洲精品爽爽| 亚洲国产精品网站在线播放 | 一本色道久久88亚洲精品综合| 老司机亚洲精品影院| 亚洲国产精品自在线一区二区| 亚洲国产精品成人精品无码区| 在线亚洲精品自拍| 亚洲午夜国产精品无码| 浮力影院亚洲国产第一页| 亚洲婷婷国产精品电影人久久| 亚洲午夜无码片在线观看影院猛| 亚洲精品99久久久久中文字幕| www.亚洲精品.com| 亚洲视频一区二区| 国产亚洲精品自在久久| 亚洲国语精品自产拍在线观看| 亚洲精品电影天堂网| 亚洲国产精品xo在线观看| 亚洲影院天堂中文av色|