<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, 評(píng)論 - 132, 引用 - 0
    數(shù)據(jù)加載中……

    【Eclipse插件開(kāi)發(fā)】Java基本類加載原理 VS 插件類加載原理

                標(biāo)題說(shuō)明了一切,我想說(shuō)的就是如果你在做Eclipse插件開(kāi)發(fā),想真正搞清楚Eclipse插件類加載,那么Java基本類加載原理是基礎(chǔ),無(wú)法逾越!!!我會(huì)舉一個(gè)小例子來(lái)簡(jiǎn)單說(shuō)明一下
                
            【情景】
              例如我們?cè)诘讓幽K插件(就叫做Host)中做了一個(gè)解析器實(shí)現(xiàn)(什么解析器就別管了),對(duì)應(yīng)類型為IParser(com.my.host.parser.IParser),簡(jiǎn)單定義如下:
    1 public interface IParser {
    2     public Object parse(Object input) throws CoreException;
    3 }
             
            基本的原則告訴我們:如果一個(gè)實(shí)例的創(chuàng)建過(guò)程較為負(fù)責(zé),則因該把這種實(shí)例的創(chuàng)建和實(shí)例的使用解耦合。于是,我們?cè)贖ost插件中提供了一個(gè)如下的工廠類:
     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"創(chuàng)建工廠失敗:" + 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"創(chuàng)建工廠失敗:" + clazz, e));
    38         }
    39     }
    40 }
    41 
            這里的簡(jiǎn)單工廠中創(chuàng)建方法返回的是IParser接口類型,目的就是為了保證可以創(chuàng)建子類型的靈活性,同時(shí)確保對(duì)外提供的接口是一致的,有助于客戶端基于接口編程(說(shuō)的有點(diǎn)上綱上線了~_~)

            同時(shí)我們?cè)贖ost插件中,也提供了一個(gè)默認(rèn)的IParser實(shí)現(xiàn),就叫做DefaultParser吧。那到這里我們的Host插件共提供了如下類型:
            com.my.host.parser.IParser                     解析器接口定義
            com.my.host.parser.ParserFactory          解析器工廠
            com.my.host.parser.impl.DefaultParser    解析器接口默認(rèn)實(shí)現(xiàn)

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

    第二種,直接使用Class.forName(),還是不用你Host中的工廠。也是俗了點(diǎn),但也沒(méi)問(wèn)題,為什么沒(méi)問(wèn)題,可能就沒(méi)有想清楚了~_~
     1 package com.my.extension.model;
     2 
     3 public class Customer {
     4     public void doOperation(Object input) throws CoreException{
     5         try {
     6             //使用默認(rèn)的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 }
    疑惑了:第二種使用方式為什么沒(méi)問(wèn)題,第三種怎么就有問(wèn)題了?代碼實(shí)現(xiàn)中都是Class.forName("").newInstance();調(diào)用啊???

    大致錯(cuò)誤原因:
            這個(gè)時(shí)候如果你只基本熟悉Eclipse的插件類加載機(jī)制(會(huì)去找所依賴的插件中的類型...),可能一時(shí)半會(huì)想不清楚。Java的類加載基本原理中有一條:Class.forName()調(diào)用方式加載類型所默認(rèn)使用的類加載器實(shí)例是加載當(dāng)前類型的類加載器。對(duì)于在Extension插件Customer中調(diào)用Class.forName()使用的是加載Customer類型的類加載器,也就是Extension插件的唯一類加載器;對(duì)于在Host插件中的ParserFactory中調(diào)用Class.forName()則使用的加載ParserFactory類型的類加載器實(shí)例,也就是Host插件的唯一類加載器。你想讓Host插件類加載器去加載一個(gè)在Extension插件中定義的類型,注意Extension插件是依賴于Host插件的啊,根據(jù)Eclipse插件類記載規(guī)則,這種加載請(qǐng)求無(wú)法從Host插件類加載器委托到Extension類加載器(說(shuō)明:使用擴(kuò)展點(diǎn)機(jī)制可以,extension registry會(huì)幫你委托這一個(gè)請(qǐng)求,找到對(duì)應(yīng)的BundleHost...)。如果你想讓Extension插件的類加載器去加載Host中定義的切export出來(lái)的類型,Extension插件的類加載器會(huì)把這個(gè)請(qǐng)求合理的委托給Host插件類加載器。


    第四種:用一把工廠,指定類加載器。由于com.my.extension.parser.MyParserImpl本身就和Customer定義在同一插件中,所以公用同一插件類加載器實(shí)例,兩者對(duì)于Extension插件來(lái)說(shuō)都是local class,加載肯定沒(méi)問(wèn)題。
     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 }

    以上是舉了一個(gè)小例子,僅僅是為了說(shuō)明一個(gè)道理:掌握J(rèn)ava類加載基本原理是掌握Eclipse插件類加載原理的基礎(chǔ),不可逾越!!!如果讓你在一個(gè)插件應(yīng)用中寫(xiě)一個(gè)較為負(fù)責(zé)的自定義類加載器,但靠背一點(diǎn)Eclipse類加載的規(guī)則,那更不夠了...

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


    本博客中的所有文章、隨筆除了標(biāo)題中含有引用或者轉(zhuǎn)載字樣的,其他均為原創(chuàng)。轉(zhuǎn)載請(qǐng)注明出處,謝謝!

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


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲av乱码中文一区二区三区| 一二三四在线播放免费观看中文版视频 | 亚洲成A人片在线观看无码不卡 | 国产成人人综合亚洲欧美丁香花| 亚洲av无码一区二区三区不卡 | 曰批免费视频播放免费| 亚洲精品福利在线观看| 永久免费av无码不卡在线观看| 免费日本一区二区| 一级一级一片免费高清| 亚洲av午夜国产精品无码中文字| 亚洲精品美女久久久久| 亚洲AV无码久久精品蜜桃| 亚洲精品久久久www| 国产精品无码素人福利免费| 免费国产成人高清在线观看网站| 无码av免费一区二区三区| 国产福利在线观看永久免费| 看Aⅴ免费毛片手机播放| 亚洲午夜无码久久| 亚洲剧场午夜在线观看| 久久精品国产亚洲AV无码娇色| 亚洲精品无码高潮喷水在线| 亚洲天堂免费在线视频| 免费A级毛片无码久久版| 韩国二级毛片免费播放| 国产成人免费高清激情视频| 午夜国产精品免费观看| 国产成人精品久久免费动漫| 中文字幕成人免费视频| 亚洲免费中文字幕| 最近免费中文字幕高清大全| 91成人在线免费视频| 69视频免费观看l| 2020久久精品国产免费| 免费电视剧在线观看| 黄瓜视频高清在线看免费下载| 好爽…又高潮了毛片免费看| 精品无码国产污污污免费| 国产无遮挡吃胸膜奶免费看视频| 国产大片91精品免费看3|