<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>+Passion=笨笨</title>
    <description></description>
    <link>http://kapokfly.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>Maximum number of open files exceeded</title>
        <author>kapok_fly</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://kapokfly.javaeye.com">kapok_fly</a>&nbsp;
          链接：<a href="http://kapokfly.javaeye.com/blog/59690" style="color:red;">http://kapokfly.javaeye.com/blog/59690</a>&nbsp;
          发表时间: 2007年03月14日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><font face="Arial"></font></p>
<p><font face="Arial"><a href="http://www.ftponline.com/weblogicpro/2005_01/magazine/columns/troubleshootingdiary/default_pf.aspx">http://www.ftponline.com/weblogicpro/2005_01/magazine/columns/troubleshootingdiary/default_pf.aspx</a></font></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://kapokfly.javaeye.com/blog/59690#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 14 Mar 2007 01:50:21 +0800</pubDate>
        <link>http://kapokfly.javaeye.com/blog/59690</link>
        <guid>http://kapokfly.javaeye.com/blog/59690</guid>
      </item>
      <item>
        <title>English -- Copy</title>
        <author>kapok_fly</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://kapokfly.javaeye.com">kapok_fly</a>&nbsp;
          链接：<a href="http://kapokfly.javaeye.com/blog/58394" style="color:red;">http://kapokfly.javaeye.com/blog/58394</a>&nbsp;
          发表时间: 2007年03月09日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Please approve my absence&nbsp;on 13th March 2007, since i am planning&nbsp;to go to my native to attend our&nbsp;family&nbsp;Get Together.&nbsp;
          <br/>
          <span style="color:red;">
            <a href="http://kapokfly.javaeye.com/blog/58394#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 09 Mar 2007 02:06:00 +0800</pubDate>
        <link>http://kapokfly.javaeye.com/blog/58394</link>
        <guid>http://kapokfly.javaeye.com/blog/58394</guid>
      </item>
      <item>
        <title>Oracle With 语法 示例</title>
        <author>kapok_fly</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://kapokfly.javaeye.com">kapok_fly</a>&nbsp;
          链接：<a href="http://kapokfly.javaeye.com/blog/48406" style="color:red;">http://kapokfly.javaeye.com/blog/48406</a>&nbsp;
          发表时间: 2007年01月18日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><font size="2">Oracle with语句示例</font> </p>
<p><br />
<font size="2">WITH a AS (SELECT * FROM bd_member WHERE ROWNUM&lt;10), <br />
b AS (SELECT * FROM tp_trade_card)<br />
select A.MEMBER_NAME,<br />
B.CARD_NO<br />
from A,<br />
B<br />
where A.BD_MEMBER_ID = B.BD_MEMBER_ID</font> </p>
<p>&nbsp;</p>
<p>Google Search: <font face="Arial">Oracle +with 视图就可以得到结果...</font></p>
<p>&nbsp;</p>
<p>
<table cellspacing="0" border="0" bordercolor="#111111" id="table2" width="618" cellpadding="0" style="BORDER-COLLAPSE: collapse">
    <tbody>
        <tr>
            <td width="438" style="FONT-SIZE: 11px; COLOR: #000">
            <div><font size="6" color="#000000">Oracle WITH clause<br />
            </font><em><font size="2"><font color="#000000"><br />
            Oracle Tips by Burleson Consulting</font><br />
            &nbsp;</font></em></div>
            </td>
        </tr>
    </tbody>
</table>
</p>
<div align="left">
<table cellspacing="0" border="0" bordercolor="#111111" id="table3" width="574" cellpadding="0" style="BORDER-COLLAPSE: collapse">
    <tbody>
        <tr>
            <td valign="top" width="574">
            <table cellspacing="0" border="0" id="table4" align="center" width="574" cellpadding="0">
                <tbody>
                    <tr>
                        <td height="100%" align="center" valign="top" width="574">
                        <table cellspacing="0" border="0" id="table5" align="center" width="615" cellpadding="10">
                            <tbody>
                                <tr>
                                    <td align="left" width="595"><strong>
                                    <div><strong><font size="6"><font size="5" color="#000000">About Oracle WITH clause </font></font></strong></div>
                                    </strong>
                                    <div>Starting in Oracle9i release 2 we see an incorporation of the SQL-99 &ldquo;WITH clause&rdquo;, a tool for materializing subqueries to save Oracle from having to re-compute them multiple times.<br />
                                    <br />
                                    The SQL &ldquo;WITH clause&rdquo; is very similar to the use of Global temporary tables (GTT), a technique that is often used to improve query speed for complex subqueries. Here are some important notes about the Oracle &ldquo;WITH clause&rdquo;:<br />
                                    <br />
                                    &nbsp;&nbsp; &bull; The SQL &ldquo;WITH clause&rdquo; only works on Oracle 9i release 2 and beyond.<br />
                                    &nbsp;&nbsp; &bull; Formally, the &ldquo;WITH clause&rdquo; is called subquery factoring<br />
                                    &nbsp;&nbsp; &bull; The SQL &ldquo;WITH clause&rdquo; is used when a subquery is executed multiple times<br />
                                    &nbsp;&nbsp; &bull; Also useful for recursive queries (SQL-99, but not Oracle SQL)<br />
                                    <br />
                                    To keep it simple, the following example only references the aggregations once, where the SQL &ldquo;WITH clause&rdquo; is normally used when an aggregation is referenced multiple times in a query. </div>
                                    <div>We can also use the SQL-99 &ldquo;WITH clause&rdquo; instead of temporary tables. The Oracle SQL &ldquo;WITH clause&rdquo; will compute the aggregation once, give it a name, and allow us to reference it (maybe multiple times), later in the query.<br />
                                    <br />
                                    The SQL-99 &ldquo;WITH clause&rdquo; is very confusing at first because the SQL statement does not begin with the word SELECT. Instead, we use the &ldquo;WITH clause&rdquo; to start our SQL query, defining the aggregations, which can then be named in the main query as if they were &ldquo;real&rdquo; tables:<br />
                                    <br />
                                    <font size="2">WITH <br />
                                    subquery_name<br />
                                    AS<br />
                                    (the aggregation SQL statement)<br />
                                    SELECT<br />
                                    (query naming subquery_name);</font><br />
                                    <br />
                                    Retuning to our oversimplified example, let&rsquo;s replace the temporary tables with the SQL &ldquo;WITH&nbsp; clause&rdquo;:<br />
                                    <br />
                                    <font size="2">WITH<br />
                                    sum_sales AS <br />
                                    &nbsp; select /*+ materialize */ <br />
                                    &nbsp;&nbsp;&nbsp; sum(quantity) all_sales from stores<br />
                                    number_stores AS <br />
                                    &nbsp; select /*+ materialize */ <br />
                                    &nbsp;&nbsp;&nbsp; count(*) nbr_stores from stores<br />
                                    sales_by_store AS<br />
                                    &nbsp; select /*+ materialize */ <br />
                                    &nbsp; store_name, sum(quantity) store_sales from <br />
                                    &nbsp; store natural join sales<br />
                                    SELECT<br />
                                    &nbsp;&nbsp; store_name<br />
                                    FROM<br />
                                    &nbsp;&nbsp; store,<br />
                                    &nbsp;&nbsp; sum_sales,<br />
                                    &nbsp;&nbsp; number_stores,<br />
                                    &nbsp;&nbsp; sales_by_store<br />
                                    where<br />
                                    &nbsp;&nbsp; store_sales &gt; (all_sales / nbr_stores)<br />
                                    ;</font><br />
                                    <br />
                                    Note the use of the Oracle undocumented &ldquo;materialize&rdquo; hint in the &ldquo;WITH clause&rdquo;. The Oracle materialize hint is used to ensure that the Oracle cost-based optimizer materializes the temporary tables that are created inside the &ldquo;WITH&rdquo; clause. This is not necessary in Oracle10g, but it helps ensure that the tables are only created one time.<br />
                                    <br />
                                    It should be noted that the &ldquo;WITH clause&rdquo; does not yet fully-functional within Oracle SQL and it does not yet support the use of &ldquo;WITH clause&rdquo; replacement for &ldquo;CONNECT BY&rdquo; when performing recursive queries.<br />
                                    <br />
                                    To see how the &ldquo;WITH clause&rdquo; is used in ANSI SQL-99 syntax, here is an excerpt from Jonathan Gennick&rsquo;s great work &ldquo;Understanding the WITH Clause&rdquo; showing the use of the SQL-99 &ldquo;WITH clause&rdquo; to traverse a recursive bill-of-materials hierarchy</div>
                                    <p>The SQL-99 &ldquo;WITH clause&rdquo; is very confusing at first because the SQL statement does not begin with the word SELECT. Instead, we use the &ldquo;WITH clause&rdquo; to start our SQL query, defining the aggregations, which can then be named in the main query as if they were &ldquo;real&rdquo; tables:<br />
                                    <br />
                                    <font size="1">WITH <br />
                                    subquery_name<br />
                                    AS<br />
                                    (the aggregation SQL statement)<br />
                                    SELECT<br />
                                    (query naming subquery_name);</font> </p>
                                    <div><br />
                                    Retuning to our oversimplified example, let&rsquo;s replace the temporary tables with the SQL &ldquo;WITH&rdquo; clause&rdquo;:<br />
                                    &nbsp;</div>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
</div>
          <br/>
          <span style="color:red;">
            <a href="http://kapokfly.javaeye.com/blog/48406#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 18 Jan 2007 19:11:35 +0800</pubDate>
        <link>http://kapokfly.javaeye.com/blog/48406</link>
        <guid>http://kapokfly.javaeye.com/blog/48406</guid>
      </item>
      <item>
        <title>周末来了, 笑话一则</title>
        <author>kapok_fly</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://kapokfly.javaeye.com">kapok_fly</a>&nbsp;
          链接：<a href="http://kapokfly.javaeye.com/blog/43268" style="color:red;">http://kapokfly.javaeye.com/blog/43268</a>&nbsp;
          发表时间: 2007年01月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <font size="2" color="#000000" face="宋体"><span style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体">说兔子跟街上走着，迎面碰上了老狼。老狼伸手就给他一大嘴巴，</span></font><font color="#000000"><span lang="EN-US" style="COLOR: black">&ldquo;</span></font><font color="#000000" face="宋体"><span style="COLOR: black; FONT-FAMILY: 宋体">让你丫不戴帽子</span></font><font color="#000000"><span lang="EN-US" style="COLOR: black">&rdquo;</span></font><font color="#000000" face="宋体"><span style="COLOR: black; FONT-FAMILY: 宋体">。</span></font><font color="#000000"><span lang="EN-US" style="COLOR: black"> <br />
<br />
</span></font><font color="#000000" face="宋体"><span style="COLOR: black; FONT-FAMILY: 宋体">兔子很郁闷地回家了，弄一帽子戴着。</span></font><font color="#000000"><span lang="EN-US" style="COLOR: black"> <br />
<br />
</span></font><font color="#000000" face="宋体"><span style="COLOR: black; FONT-FAMILY: 宋体">第二天又碰上老狼了，又挨了一大嘴巴，</span></font><font color="#000000"><span lang="EN-US" style="COLOR: black">&ldquo;</span></font><font color="#000000" face="宋体"><span style="COLOR: black; FONT-FAMILY: 宋体">让你丫戴帽子</span></font><font color="#000000"><span lang="EN-US" style="COLOR: black">&rdquo;</span></font><font color="#000000" face="宋体"><span style="COLOR: black; FONT-FAMILY: 宋体">。</span></font><font color="#000000"><span lang="EN-US" style="COLOR: black"> <br />
<br />
</span></font><font color="#000000" face="宋体"><span style="COLOR: black; FONT-FAMILY: 宋体">如是几次，总挨打。兔子想，这么老挨打不是个事儿啊，不行，我得找老虎投诉去。</span></font><font color="#000000"><span lang="EN-US" style="COLOR: black"> <br />
<br />
</span></font><font color="#000000" face="宋体"><span style="COLOR: black; FONT-FAMILY: 宋体">刚到老虎家门口，就听老虎在屋里说话。</span></font><font color="#000000"><span lang="EN-US" style="COLOR: black"> <br />
<br />
&ldquo;</span></font><font color="#000000" face="宋体"><span style="COLOR: black; FONT-FAMILY: 宋体">你也不能老这么蛮不讲理打兔子阿，回头兔子找我投诉来，我也不好罩着你啊。好歹咱面子上得过得去，我教你一招。</span></font><font color="#000000"><span lang="EN-US" style="COLOR: black"> <br />
<br />
</span></font><font color="#000000" face="宋体"><span style="COLOR: black; FONT-FAMILY: 宋体">下回你见着兔子，跟他说：给我弄点儿洗衣服的来。他给你拿肥皂来，你就打他一顿的，说我要的是洗衣粉，谁让你拿肥皂。他拿来洗衣粉，你也能打，说我要肥皂，谁让你拿洗衣粉。</span></font><font color="#000000"><span lang="EN-US" style="COLOR: black"> <br />
<br />
</span></font><font color="#000000" face="宋体"><span style="COLOR: black; FONT-FAMILY: 宋体">要不然你跟他说，去，给我找个女人来。他给你找个胖的，你打他一顿说我要瘦的；给你找个瘦的，你也打一顿，说我要胖的。</span></font><font color="#000000"><span lang="EN-US" style="COLOR: black"> <br />
<br />
</span></font><font color="#000000" face="宋体"><span style="COLOR: black; FONT-FAMILY: 宋体">这样不结了，你也能打他，我面子上也能说得过去。</span></font><font color="#000000"><span lang="EN-US" style="COLOR: black">&rdquo; <br />
<br />
</span></font><font color="#000000" face="宋体"><span style="COLOR: black; FONT-FAMILY: 宋体">兔子一听，得，咱也别投诉了，回家吧。</span></font><font color="#000000"><span lang="EN-US" style="COLOR: black"> <br />
<br />
</span></font><font color="#000000" face="宋体"><span style="COLOR: black; FONT-FAMILY: 宋体">第二天，兔子在街上又撞上老狼。老狼大喝一声：去，给我找点儿洗衣服的来。</span></font><font color="#000000"><span lang="EN-US" style="COLOR: black"> <br />
<br />
</span></font><font color="#000000" face="宋体"><span style="COLOR: black; FONT-FAMILY: 宋体">兔子不慌不忙：你是要洗衣粉阿，还是要肥皂啊？</span></font><font color="#000000"><span lang="EN-US" style="COLOR: black"> <br />
<br />
</span></font><font color="#000000" face="宋体"><span style="COLOR: black; FONT-FAMILY: 宋体">老狼一听，嗯？有一手阿。又说：去，给我找个女人来。</span></font><font color="#000000"><span lang="EN-US" style="COLOR: black"> <br />
<br />
</span></font><font color="#000000" face="宋体"><span style="COLOR: black; FONT-FAMILY: 宋体">兔子还是不慌不忙：你是要胖的啊，还是瘦的？</span></font><font color="#000000"><span lang="EN-US" style="COLOR: black"> <br />
<br />
</span></font><font color="#000000" face="宋体"><span style="COLOR: black; FONT-FAMILY: 宋体">老狼一听勃然大怒，伸手就给兔子一个大嘴巴，</span></font><font color="#000000"><span lang="EN-US" style="COLOR: black"> <br />
</span></font><font color="#000000" face="宋体"><span style="COLOR: black; FONT-FAMILY: 宋体">让你丫不戴帽子！</span></font>
          <br/>
          <span style="color:red;">
            <a href="http://kapokfly.javaeye.com/blog/43268#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 05 Jan 2007 17:11:01 +0800</pubDate>
        <link>http://kapokfly.javaeye.com/blog/43268</link>
        <guid>http://kapokfly.javaeye.com/blog/43268</guid>
      </item>
      <item>
        <title>百度和Google新域名:-)</title>
        <author>kapok_fly</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://kapokfly.javaeye.com">kapok_fly</a>&nbsp;
          链接：<a href="http://kapokfly.javaeye.com/blog/43266" style="color:red;">http://kapokfly.javaeye.com/blog/43266</a>&nbsp;
          发表时间: 2007年01月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><font face="Arial"><a href="http://www.mamashuojiusuannizhucedeyumingzaichanggoogledounengsousuochulai.cn">www.mamashuojiusuannizhucedeyumingzaichanggoogledounengsousuochulai.cn</a></font></p>
<p><font face="Arial">中文拼音：&quot;妈妈说就算你注册的域名再长GOOGLE都能搜索出来&quot;</font></p>
<p><font face="Arial"><a href="http://www.mamashuojiusuannizhucedeyumingzaichangbaidudounengsousuochulai.cn">www.mamashuojiusuannizhucedeyumingzaichangbaidudounengsousuochulai.cn</a><br />
中文拼音：&quot;妈妈说就算你注册的域名再长百度都能搜索出来&quot;</font></p>
          <br/>
          <span style="color:red;">
            <a href="http://kapokfly.javaeye.com/blog/43266#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 05 Jan 2007 17:04:02 +0800</pubDate>
        <link>http://kapokfly.javaeye.com/blog/43266</link>
        <guid>http://kapokfly.javaeye.com/blog/43266</guid>
      </item>
      <item>
        <title>Java类装载体系中的隔离性</title>
        <author>kapok_fly</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://kapokfly.javaeye.com">kapok_fly</a>&nbsp;
          链接：<a href="http://kapokfly.javaeye.com/blog/43213" style="color:red;">http://kapokfly.javaeye.com/blog/43213</a>&nbsp;
          发表时间: 2007年01月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p class="title" align="center">原文链接：<font face="Arial"><a href="http://gceclub.sun.com.cn/yuanchuang/week-9/classloader.html">http://gceclub.sun.com.cn/yuanchuang/week-9/classloader.html</a></font></p>
<p class="title" align="center">Java类装载体系中的隔离性</p>
<p align="center">作者：<a href="http://gceclub.sun.com.cn/yuanchuang/week-9/classloader.html#author">盛戈歆</a></p>
<a name="author"></a>
<p><strong>作者简介</strong></p>
<p class="normal">盛戈歆，软件工程师，你可以通过<a href="mailto:shenggexin@topwaver.com">shenggexin@topwaver.com</a>与他联系。</p>
<p><strong>正文</strong></p>
<p class="normal">Java中类的查找与装载出现的问题总是会时不时出现在Java程序员面前，这并不是什么丢脸的事情，相信没有一个Java程序员没遇到过ClassNotException,因此不要为被人瞅见自己也犯这样的错误而觉得不自然，但是在如果出现了ClassNotFoundException后异常后一脸的茫然，那我想你该了解一下java的类装载的体制了，同时为了进行下面的关于类装载器之间的隔离性的讨论，我们先简单介绍一下类装载的体系结构。</p>
<p><strong>1. Java类装载体系结构</strong></p>
<p class="normal">装载类的过程非常简单：查找类所在位置，并将找到的Java类的字节码装入内存，生成对应的Class对象。Java的类装载器专门用来实现这样的过程，JVM并不止有一个类装载器，事实上，如果你愿意的话，你可以让JVM拥有无数个类装载器，当然这除了测试JVM外，我想不出还有其他的用途。你应该已经发现到了这样一个问题，类装载器自身也是一个类，它也需要被装载到内存中来，那么这些类装载器由谁来装载呢，总得有个根吧？没错，确实存在这样的根，它就是神龙见首不见尾的Bootstrap ClassLoader. 为什么说它神龙见首不见尾呢，因为你根本无法在Java代码中抓住哪怕是它的一点点的尾巴，尽管你能时时刻刻体会到它的存在，因为java的运行环境所需要的所有类库，都由它来装载，而它本身是C++写的程序，可以独立运行,可以说是JVM的运行起点,伟大吧。在Bootstrap完成它的任务后，会生成一个AppClassLoader(实际上之前系统还会使用扩展类装载器ExtClassLoader，它用于装载Java运行环境扩展包中的类),这个类装载器才是我们经常使用的，可以调用ClassLoader.getSystemClassLoader() 来获得，我们假定程序中没有使用类装载器相关操作设定或者自定义新的类装载器，那么我们编写的所有java类通通会由它来装载，值得尊敬吧。<font color="#ff0000">AppClassLoader查找类的区域就是耳熟能详的Classpath，也是初学者必须跨过的门槛，有没有灵光一闪的感觉，我们按照它的类查找范围给它取名为<strong><font size="4" style="BACKGROUND-COLOR: #ffff99">类路径类装载器</font></strong></font>。还是先前假定的情况，当Java中出现新的类，AppClassLoader首先在类传递给它的父类类装载器，也就是Extion ClassLoader，询问它是否能够装载该类，如果能，那AppClassLoader就不干这活了，同样Extion ClassLoader在装载时，也会先问问它的父类装载器。我们可以看出类装载器实际上是一个树状的结构图，每个类装载器有自己的父亲，类装载器在装载类时，总是先让自己的父类装载器装载(多么尊敬长辈),如果父类装载器无法装载该类时，自己就会动手装载，如果它也装载不了，那么对不起，它会大喊一声：Exception，class not found。有必要提一句，当由直接使用类路径装载器装载类失败抛出的是NoClassDefFoundException异常。如果使用自定义的类装载器loadClass方法或者ClassLoader的findSystemClass方法装载类，如果你不去刻意改变，那么抛出的是ClassNotFoundException。</p>
<p class="normal">我们简短总结一下上面的讨论：</p>
<p class="normal">1.JVM类装载器的体系结构可以看作是树状结构。</p>
<p class="normal">2.父类装载器优先装载。在父类装载器装载失败的情况下再装载，如果都装载失败则抛出ClassNotFoundException或者NoClassDefFoundError异常。</p>
<p class="normal">那么我们的类在什么情况下被装载的呢？</p>
<strong>2. 类如何被装载</strong>
<p>&nbsp;</p>
<p class="normal">在java2中，JVM是如何装载类的呢，可以分为两种类型，一种是隐式的类装载，一种式显式的类装载。</p>
<strong>2.1 隐式的类装载</strong>
<p>&nbsp;</p>
<p class="normal">隐式的类装载是编码中最常用得方式：</p>
<pre>A b = new A();
</pre>
<p class="normal">如果程序运行到这段代码时还没有A类，那么JVM会请求装载当前类的类装器来装载类。问题来了，我把代码弄得复杂一点点，但依旧没有任何难度，请思考JVM得装载次序：</p>
<pre>package test;
Public class A{
    public void static main(String args[]){
        B b ＝ new B();
    }
}

class B{C c;}

class C{}
</pre>
<p class="normal">揭晓答案，类装载的次序为A-&gt;B，而类C根本不会被JVM理会,先不要惊讶，仔细想想，这不正是我们最需要得到的结果。我们仔细了解一下JVM装载顺序。当使用Java A命令运行A类时，JVM会首先要求类路径类装载器(AppClassLoader)装载A类，但是这时只装载A，不会装载A中出现的其他类(B类)，接着它会调用A中的main函数，直到运行语句b ＝ new B()时，JVM发现必须装载B类程序才能继续运行，于是类路径类装载器会去装载B类，虽然我们可以看到B中有有C类的声明，但是并不是实际的执行语句，所以并不去装载C类，也就是说JVM按照运行时的有效执行语句，来决定是否需要装载新类，从而装载尽可能少的类，这一点和编译类是不相同的。</p>
<p><strong>2.2 显式的类装载</strong></p>
<p class="normal">使用显示的类装载方法很多，我们都装载类test.A为例。</p>
<p class="normal">使用Class类的forName方法。它可以指定装载器，也可以使用装载当前类的装载器。例如：</p>
<pre>Class.forName(&quot;test.A&quot;);
它的效果和
Class.forName(&quot;test.A&quot;,true,this.getClass().getClassLoader());
是一样的。
</pre>
<p class="normal">使用<font size="4" color="#ff0000" style="BACKGROUND-COLOR: #ffff99"><strong>类路径类装载器</strong></font>装载.</p>
<pre>ClassLoader.getSystemClassLoader().loadClass(&quot;test.A&quot;);
</pre>
<p class="normal">使用当前进程上下文的使用的类装载器进行装载，这种装载类的方法常常被有着复杂类装载体系结构的系统所使用。</p>
<pre>Thread.currentThread().getContextClassLoader().loadClass(&quot;test.A&quot;)
</pre>
<p class="normal">使用自定义的类装载器装载类</p>
<pre>public class MyClassLoader extends URLClassLoader{
public MyClassLoader() {
        super(new URL[0]);
    }
}
MyClassLoader myClassLoader = new MyClassLoader();
myClassLoader.loadClass(&quot;test.A&quot;);
</pre>
<p class="normal">MyClassLoader继承了URLClassLoader类，这是JDK核心包中的类装载器，在没有指定父类装载器的情况下，类路径类装载器就是它的父类装载器，MyClassLoader并没有增加类的查找范围，因此它和类路径装载器有相同的效果。</p>
<p class="normal">我们已经知道Java的类装载器体系结构为树状，多个类装载器可以指定同一个类装载器作为自己的父类，每个子类装载器就是树状结构的一个分支，当然它们又可以个有子类装载器类装载器，类装载器也可以没有父类装载器，这时Bootstrap类装载器将作为它的隐含父类，实际上Bootstrap类装载器是所有类装载器的祖先，也是树状结构的根。这种树状体系结构，以及父类装载器优先的机制，为我们编写自定义的类装载器提供了便利，同时可以让程序按照我们希望的方式进行类的装载。例如某个程序的类装载器体系结构图如下：</p>
<p align="center"><img src="http://gceclub.sun.com.cn/yuanchuang/week-9/classloader.gif" border="0" height="287" alt="" width="427" /></p>
<p align="center">图2：某个程序的类装载器的结构</p>
<p class="normal">解释一下上面的图，ClassLoaderA为自定义的类装载器，它的父类装载器为类路径装载器，它有两个子类装载器ClassLoaderAA和ClassLaderAB，ClassLoaderB为程序使用的另外一个类装载器，它没有父类装载器，但有一个子类装载器ClassLoaderBB。你可能会说，见鬼，我的程序怎么会使用这么复杂的类装载器结构。为了进行下面的讨论，暂且委屈一下。</p>
<p><strong>3. 奇怪的隔离性</strong></p>
<p class="normal">我们不难发现，图2中的类装载器AA和AB， AB和BB，AA和B等等位于不同分支下，他们之间没有父子关系，我不知道如何定义这种关系，姑且称他们位于不同分支下。两个位于不同分支的类装载器具有隔离性，这种隔离性使得在分别使用它们装载同一个类，也会在内存中出现两个Class类的实例。因为被具有隔离性的类装载器装载的类不会共享内存空间，使得使用一个类装载器不可能完成的任务变得可以轻而易举，例如类的静态变量可能同时拥有多个值（虽然好像作用不大），因为就算是被装载类的同一静态变量，它们也将被保存不同的内存空间，又例如程序需要使用某些包，但又不希望被程序另外一些包所使用，很简单，编写自定义的类装载器。类装载器的这种隔离性在许多大型的软件应用和服务程序得到了很好的应用。下面是同一个类静态变量为不同值的例子。</p>
<pre>package test;
public class A {
  public static void main( String[] args ) {
    try {
      //定义两个类装载器
      MyClassLoader aa= new MyClassLoader();
      MyClassLoader bb = new MyClassLoader();

      //用类装载器aa装载testb.B类
      Class clazz=aa.loadClass(&quot;testb. B&quot;);
      Constructor constructor= 
        clazz.getConstructor(new Class[]{Integer.class});
      Object object = 
	    constructor.newInstance(new Object[]{new Integer(1)});
      Method method = 
	    clazz.getDeclaredMethod(&quot;printB&quot;,new Class[0]);

      //用类装载器bb装载testb.B类
      Class clazz2=bb.loadClass(&quot;testb. B&quot;);
      Constructor constructor2 = 
        clazz2.getConstructor(new Class[]{Integer.class});
      Object object2 = 
	    constructor2.newInstance(new Object[]{new Integer(2)});
      Method method2 = 
	    clazz2.getDeclaredMethod(&quot;printB&quot;,new Class[0]);

      //显示test.B中的静态变量的值 
      method.invoke( object,new Object[0]);
      method2.invoke( object2,new Object[0]);
    } catch ( Exception e ) {
      e.printStackTrace();
    }
  }
}
</pre>
<br />
<pre>//Class B 必须位于MyClassLoader的查找范围内，
//而不应该在MyClassLoader的父类装载器的查找范围内。
package testb;
public class B {
    static int b ;

    public B(Integer testb) {
        b = testb.intValue();
    }

    public void printB() {
        System.out.print(&quot;my static field b is &quot;, b);
    }
}
</pre>
<br />
<pre>public class MyClassLoader extends URLClassLoader{
  private static File file = new File(&quot;c:\\classes &quot;);
  //该路径存放着class B，但是没有class A

  public MyClassLoader() {
    super(getUrl());
  }

  public static URL[] getUrl() {
    try {
      return new URL[]{file.toURL()};
    } catch ( MalformedURLException e ) {
      return new URL[0];
    }
  }
}
</pre>
<p class="normal">程序的运行结果为：</p>
<pre>my static field b is 1
my static field b is 2
</pre>
<p class="normal">程序的结果非常有意思，从编程者的角度，我们甚至可以把不在同一个分支的类装载器看作不同的java虚拟机，因为它们彼此觉察不到对方的存在。程序在使用具有分支的类装载的体系结构时要非常小心，弄清楚每个类装载器的类查找范围，尽量避免父类装载器和子类装载器的类查找范围中有相同类名的类（包括包名和类名），下面这个例子就是用来说明这种情况可能带来的问题。</p>
<p class="normal">假设有相同名字却不同版本的接口 A，</p>
<pre>版本 1：
package test;
Intefer Same{ public String getVersion(); }
版本 2：
Package test;
Intefer Same{ public String getName(); }
</pre>
<p class="normal">接口A两个版本的实现：</p>
<pre>版本1的实现
package test;
public class Same1Impl implements Same {
public String getVersion(){ return &quot;A version 1&quot;;}
}
版本2的实现
public class Same 2Impl implements Same {
public String getName(){ return &quot;A version 2&quot;;}
}
</pre>
<p class="normal">我们依然使用图2的类装载器结构，首先将版本1的Same和Same的实现类Same1Impl打成包same1.jar，将版本2的Same和Same的实现类Same1Impl打成包same2.jar。现在，做这样的事情，把same1.jar放入类装载器ClassLoaderA的类查找范围中，把same2.jar放入类装器ClassLoaderAB的类查找范围中。当你兴冲冲的运行下面这个看似正确的程序。</p>
<p class="normal">实际上这个错误的是由父类载器优先装载的机制造成，当类装载器ClassLoaderAB在装载Same2Impl类时发现必须装载接口test.Same，于是按规定请求父类装载器装载，父类装载器发现了版本1的test.Same接口并兴冲冲的装载，但是却想不到Same2Impl所希望的是版本2 的test.Same，后面的事情可想而知了，异常被抛出。</p>
<p class="normal">我们很难责怪Java中暂时并没有提供区分版本的机制，如果使用了比较复杂的类装载器体系结构，在出现了某个包或者类的多个版本时，应特别注意。</p>
<p class="normal">掌握和灵活运用Java的类装载器的体系结构，对程序的系统设计，程序的实现，已经程序的调试，都有相当大的帮助。希望以上的内容能够对您有所帮助。</p>
<p class="normal">&nbsp;
<table cellspacing="1" border="1" summary="" width="90%" cellpadding="1">
    <caption>Ext1</caption>
    <tbody>
        <tr>
            <td>Class.forName(String clz);<br />
            使用调用这个语句的对象所使用的ClassLoader作为ClassLoader(1)。(请查看代码)<br />
            <br />
            Thread.currentThread().getContextClassLoader())<br />
            返回当前线程使用的ClassLoader(2)。<br />
            <br />
            <br />
            如果ClassLoader(1)&ldquo;等于&rdquo;ClassLoader(2)，那么这里的使用Class.forName(String clz)和ClassLoader(2).loadClass(String clz)就是等价的。<br />
            <br />
            如果ClassLoader(1)&ldquo;不等于&rdquo;ClassLoader(2)，那么就是不等价的。<br />
            <br />
            在框架代码中，实际情况是ClassLoader(1)往往&ldquo;不等于&rdquo;ClassLoader(2)：<br />
            即调用Class.forName(String clz)的语句所在的类的装载器不一定就是当前线程使用的类装载器。<br />
            因为：一个类装载完了在运行了，该类的所属的类装载器就确定了(不变)，而<font size="4" color="#ff0000" style="BACKGROUND-COLOR: #ffff99"><strong>在程序运行之中，线程的类装载器都随时可以通过hread.currentThread().setContextClassLoader(loader)进行改变</strong></font>(变)。</td>
        </tr>
    </tbody>
</table>
</p>
<p class="normal">&nbsp;</p>
<p class="normal">
<table cellspacing="1" border="1" summary="" width="90%" cellpadding="1">
    <tbody>
        <tr>
            <td>
            <table cellspacing="2" border="0" width="100%" cellpadding="2">
                <tbody>
                    <tr>
                        <td><span class="tpc_content">Class.forName有两个签名Class.forName(String)和Class.forName(String, boolean, ClassLoader)，最终都是调用内部native方法forName0，第一个签名实现是return forName0(className, true, ClassLoader.getCallerClassLoader())，第二个稍微复杂一些，但是大概认为是在当指定loader==null的时候使用ClassLoader.getCallerClassLoader().<br />
                        再看ClassLoader.getCallerClassLoader()怎么实现，很简单通过一个native方法得到caller class然后getClassLoader()<br />
                        现在结论很简单了，当caller class不是由current thread的context ClassLoader load的时候，两者的结果会不一致</span></td>
                    </tr>
                </tbody>
            </table>
            <p>&nbsp;</p>
            <p>&nbsp;</p>
            <p>&nbsp;</p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p class="normal">&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://kapokfly.javaeye.com/blog/43213#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 05 Jan 2007 12:46:42 +0800</pubDate>
        <link>http://kapokfly.javaeye.com/blog/43213</link>
        <guid>http://kapokfly.javaeye.com/blog/43213</guid>
      </item>
      <item>
        <title>Eclipse开发链接[Level 0]</title>
        <author>kapok_fly</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://kapokfly.javaeye.com">kapok_fly</a>&nbsp;
          链接：<a href="http://kapokfly.javaeye.com/blog/43077" style="color:red;">http://kapokfly.javaeye.com/blog/43077</a>&nbsp;
          发表时间: 2007年01月04日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><font face="Arial"></font>&nbsp;<font face="Arial">moneyice的专栏：</font></p>
<p><font face="Arial"><a href="http://blog.csdn.net/moneyice/">http://blog.csdn.net/moneyice/</a></font></p>
<p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://kapokfly.javaeye.com/blog/43077#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 04 Jan 2007 20:46:03 +0800</pubDate>
        <link>http://kapokfly.javaeye.com/blog/43077</link>
        <guid>http://kapokfly.javaeye.com/blog/43077</guid>
      </item>
      <item>
        <title>[转载]利用 Eclipse 开发基于 OSGi 的 Bundle 应用</title>
        <author>kapok_fly</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://kapokfly.javaeye.com">kapok_fly</a>&nbsp;
          链接：<a href="http://kapokfly.javaeye.com/blog/43074" style="color:red;">http://kapokfly.javaeye.com/blog/43074</a>&nbsp;
          发表时间: 2007年01月04日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <blockquote>
<p><font face="Arial"><a href="http://www-128.ibm.com/developerworks/cn/opensource/os-ecl-osgibdev/index.html">http://www-128.ibm.com/developerworks/cn/opensource/os-ecl-osgibdev/index.html</a></font></p>
<p>开放服务网关协议 (Open Services Gateway Initiative)，简称 OSGi,为网络服务定义了一个标准的、面向服务的计算环境，为用户提供了开放的、面向服务组件的、易于部署的编程模型，这个编程模型允许用户将定义好的接口规范绑定到 OSGi 运行环境中的特定Service，在构件 SOA 面向服务为中心的企业应用的过程中，OSGi 技术正发挥越来越重要的作用。在本文中，将介绍 OSGi 的概念和体系结构，并且利用 Eclipse 3.2 开发一个基于 OSGi 规范的服务应用 Bundle。通过学习本文，读者可以了解到如何开发和部署基于 OSGi 规范的 Bundle 应用。</p>
</blockquote><!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--END RESERVED FOR FUTURE USE INCLUDE FILES-->
<p><a name="N10049"><span class="atitle">OSGi 规范简介</span></a></p>
<p>OSGi 联盟建立于 1999 年，是一个非赢利机构，旨在建立一个开放的服务规范。OSGi 规范为网络服务定义了一个标准的、面向组件的计算环境，它最初的目的就是为各种嵌入式设备提供通用的软件运行平台，屏蔽设备操作系统与硬件区别的中间件平台，通过这个平台，可以对不同软件商提供的应用(OSGi 中称为 Bundle)进行组件的生命周期管理的能力，如应用组件可以从运行中被安装、升级或者移除而不需要中断设备的操作，应用组件可以动态的发现和使用其他库或者应用程序。由于 OSGi 技术具有服务组件模块化、动态加载应用等优点，正被越来越多的领域关注，如嵌入设备制造业、汽车制造业、企业应用等。目前，OSGi 联盟发布的最新的 OSGi 服务规范为 4.0，读者可以查阅参考资料了解详细信息。</p>
<br />
<table cellspacing="0" border="0" width="100%" cellpadding="0">
    <tbody>
        <tr>
            <td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" alt="" width="100%" /><br />
            <img src="http://www.ibm.com/i/c.gif" border="0" height="6" alt="" width="8" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" align="right" cellpadding="0">
    <tbody>
        <tr align="right">
            <td><img src="http://www.ibm.com/i/c.gif" height="4" alt="" width="100%" /><br />
            <table cellspacing="0" border="0" cellpadding="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" alt="" width="16" /><br />
                        </td>
                        <td align="right" valign="top"><a href="http://www-128.ibm.com/developerworks/cn/opensource/os-ecl-osgibdev/index.html#main" class="fbox"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N10052"><span class="atitle">OSGi 体系结构</span></a></p>
<p>OSGi 的体系架构是基于插件式的软件结构，包括一个 OSGi 框架和一系列插件，在 OSGi中，插件称为 Bundle，其中，OSGi 框架规范是 OSGi 规范的核心部分，它提供了一个通用的、安全可管理的 Java 框架，通过这个框架，可以支持 Bundle 服务应用的部署和扩展。Bundle 之间可以通过 Import Package 和 Require-Bundle 来共享 Java 类，在 OSGi 服务平台中，用户通过开发 Bundle 来提供需要的功能，这些 Bundle 可以动态加载和卸载，或者根据需要远程下载和升级。OSGi 体系结构图如图 1 所示：</p>
<br />
<a name="N1005D"><strong>图示1 OSGi 体系结构</strong></a><br />
<img src="http://www-128.ibm.com/developerworks/cn/opensource/os-ecl-osgibdev/images/image002.jpg" border="0" height="268" alt="图示1 OSGi 体系结构" width="320" /> <br />
<p>其中：</p>
<p>Execution Environment：</p>
<p>Bundle 应用所倚赖运行的 Java 执行环境，如 J2SE-1.4、CDC-1.0 等都是可用的执行环境。</p>
<p>Modules：</p>
<p>模块层定义了 Bundle 应用的加载策略。OSGi 框架是一个健壮并且严格定义的类加载模型。在大多数 Java 应用中，通常只有一个单独的 ClassPath，它包含了所有的 Java 类文件和资源文件，OSGi基于Java技术，对于每个实现了 BundleActivator 接口的 Bundle 应用，为它生成一个单独的 ClassLoader，使得 Bundle 应用的组织更加模块化。</p>
<p>Life Cycle：</p>
<p>生命周期层可以动态地对 Bundle 进行安装、启动、停止、升级和卸载等操作。该层基于模块层，提供了一组 API 来控制 Bundle 应用的运行时操作。</p>
<p>Service Registry 和 Services：</p>
<p>OSGi 服务层定义了一个集成在生命周期层中的动态协作模型，是一个发布、动态寻找、绑定的服务模型。一个服务通常是一个 Java 对象实现了特定的服务接口，并且通过服务注册，被绑定到 OSGi 的运行环境中。Bundle 应用可以注册发布服务，动态绑定服务，并且在服务注册状态改变时，可以接受到事件消息等。</p>
<p>Security：</p>
<p>OSGi 的安全管理是基于 Java2 安全体系的，贯穿在 OSGi 平台的所有层中，它能够对部署在 OSGi 运行环境中的 Bundle 应用进行详细的管理控制。</p>
<br />
<table cellspacing="0" border="0" width="100%" cellpadding="0">
    <tbody>
        <tr>
            <td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" alt="" width="100%" /><br />
            <img src="http://www.ibm.com/i/c.gif" border="0" height="6" alt="" width="8" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" align="right" cellpadding="0">
    <tbody>
        <tr align="right">
            <td><img src="http://www.ibm.com/i/c.gif" height="4" alt="" width="100%" /><br />
            <table cellspacing="0" border="0" cellpadding="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" alt="" width="16" /><br />
                        </td>
                        <td align="right" valign="top"><a href="http://www-128.ibm.com/developerworks/cn/opensource/os-ecl-osgibdev/index.html#main" class="fbox"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N1008E"><span class="atitle">Bundle 生命周期的状态</span></a></p>
<p>在一个动态扩展的 OSGi 环境中，OSGi 框架管理 Bundle 的安装和更新，同时也管理 Bundle 和服务之间的依赖关系。一个 Bundle 可能处于以下六个状态，如图 2 所示：</p>
<br />
<a name="N10099"><strong>图示 2 Bundle 状态图</strong></a><br />
<img src="http://www-128.ibm.com/developerworks/cn/opensource/os-ecl-osgibdev/images/image004.jpg" border="0" height="273" alt="图示 2 Bundle 状态图" width="355" /> <br />
<p>INSTALLED：安装完成，本地资源成功加载。</p>
<p>RESOLVED：依赖关系满足，这个状态意味该Bundle要么已经准备好运行，要么是被停止了。</p>
<p>STARTING：Bundle正在被启动，BundleActivator的start()方法已经被调用但是还没有返回。</p>
<p>STOPPING：Bundle正在被停止，BundleActivator的stop()方法已经被调用但是还没有返回。</p>
<p>ACTIVE：Bundle 被成功启动并且在运行。</p>
<p>UNINSTALLED：bundle被卸载并且无法进入其他状态。</p>
<p>Bundle接口定义了getState()方法来返回Bundle的状态。</p>
<br />
<table cellspacing="0" border="0" width="100%" cellpadding="0">
    <tbody>
        <tr>
            <td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" alt="" width="100%" /><br />
            <img src="http://www.ibm.com/i/c.gif" border="0" height="6" alt="" width="8" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" align="right" cellpadding="0">
    <tbody>
        <tr align="right">
            <td><img src="http://www.ibm.com/i/c.gif" height="4" alt="" width="100%" /><br />
            <table cellspacing="0" border="0" cellpadding="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" alt="" width="16" /><br />
                        </td>
                        <td align="right" valign="top"><a href="http://www-128.ibm.com/developerworks/cn/opensource/os-ecl-osgibdev/index.html#main" class="fbox"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N100BE"><span class="atitle">OSGi 标准服务</span></a></p>
<p>在 OSGi 平台之上，OSGi 联盟定义了很多服务。服务是由一个 Java Interface 来定义的，Bundle 可以实现这个接口并且把服务注册到服务注册表中去，用户可以从注册表中找到需要的服务来使用，并且可以响应特定服务的状态改变，如服务注册和服务取消。下面简单介绍一下 OSGi Release 4 的一些主要服务。OSGi 框架提供了权限管理服务，包管理服务和最初加载系统服务。这些服务是 OSGi 框架的一部分并且管理着 OSGi 框架的运作。</p>
<p>Permission Admin Service：权限管理是指 Bundle 是否许可其他的 Bundle 的代码。当前的或者其他的 Bundle 的权限可以通过这个服务来操作，一旦被设定权限，马上就生效。 Package Admin Service：Bundle 之间可以共享包内的 Java 类和资源，bundle 的更新可能需要 OSGi 框架重新解析 Bundle 之间的依赖关系，这个服务提供了 OSGi 服务平台中包的共享状态信息。</p>
<p>Start Level Service：Start Level是指一些在特定Bundle起动之前必须运行或者初始化的一系列 bundle。Start Lever Service 可以设置当前OSGi服务框架初始的Start Level，并且可以指定和查询特定Bundle的Start Level。</p>
<br />
<table cellspacing="0" border="0" width="100%" cellpadding="0">
    <tbody>
        <tr>
            <td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" alt="" width="100%" /><br />
            <img src="http://www.ibm.com/i/c.gif" border="0" height="6" alt="" width="8" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" align="right" cellpadding="0">
    <tbody>
        <tr align="right">
            <td><img src="http://www.ibm.com/i/c.gif" height="4" alt="" width="100%" /><br />
            <table cellspacing="0" border="0" cellpadding="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" alt="" width="16" /><br />
                        </td>
                        <td align="right" valign="top"><a href="http://www-128.ibm.com/developerworks/cn/opensource/os-ecl-osgibdev/index.html#main" class="fbox"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N100CD"><span class="atitle">使用 Eclipse 开发 Bundle 应用</span></a></p>
<p>Equinox 框架是 Eclipse 组织基于 OSGi Release 4 的一个实现框架，它实现了 OSGi 规范的核心框架和许多标准框架服务的实现。关于Equinox项目的详细信息，请查阅参考资料信息。在本文中，我们使用 Eclipse 3.2 平台开发两个基于 OSGi 的 Bundle 应用，其中第一个 Bundle 应用声明、实现并注册了一个姓名查询服务，用于判断所给姓名是否在已定义的查询列表中；第二个 Bundle 应用查询并引用第一个 Bundle 应用所注册的姓名查询服务，如果用户所给的姓名包含在查询列表中，将返回正确的信息，最后，将开发的 Bundle应用部署的 Equinox OSGi 框架中，用户可以在 OSGi 控制命令行中输入命令来查询关于框架和 Bundle 应用的具体信息。读者可以从参考资料中获得本文 Bundle 应用的源代码。</p>
<p>(1)创建 Plug-in Project，在 Eclipse 3.2 开发环境中，从菜单栏选择 File &gt; New &gt; Project... ，打开 New Project 向导，可以看到有Plug-in Project创建向导，创建一个Plug-in 项目。项目名为 example 的 Bundle 应用，该应用实现并注册了一个姓名查询服务，实现了 BundleActivator 接口。选择 Equinox 框架作为 Bundle 应用运行的 OSGi 服务平台。</p>
<br />
<a name="N100DB"><strong>图示 3 Plug-in 项目向导</strong></a><br />
<img src="http://www-128.ibm.com/developerworks/cn/opensource/os-ecl-osgibdev/images/image006.jpg" border="0" height="378" alt="图示 3 Plug-in 项目向导" width="403" /> <br />
<p>(2)实现OSGi服务通常需要两个步骤，首先定义所提供服务的接口，然后实现这个服务接口。在本例中，我们创建一个姓名查询服务用来查询所给姓名是否有效。首先定义姓名查询接口NameService.java。下面是该接口的源代码：</p>
<br />
<a name="N100EE"><strong>NameService Interface 源代码</strong></a><br />
<table cellspacing="0" border="1" bgcolor="#eeeeee" width="100%" cellpadding="5">
    <tbody>
        <tr>
            <td><code>
            <pre class="section">package example.service;
/**
 * A simple service interface that defines a name service.
 * A name service simply verifies the existence of a Name.
**/
public interface NameService {
	/**
     * Check for the existence of a Name.
     * @param name the Name to be checked.
     * @return true if the Name is in the list,
     *         false otherwise.
    **/
	public boolean checkName(String name);
}
</pre>
            </code></td>
        </tr>
    </tbody>
</table>
<br />
<p>该服务接口很简单，只包含一个需要实现的方法。为了将服务接口和服务实现相分离，方便其他 Bundle 引用该服务，我们通常需要将该服务接口单独放在一个包内，本例中，存放NameService.java 接口的 Java 包为 example.service。接下来，需要实现 NameService 接口，并且注册该服务。在本例中，我们用内部类实现了该接口，下面是该 Bundle 应用的部分源代码。</p>
<br />
<a name="N100FB"><strong>Example Bundle部分源代码</strong></a><br />
<table cellspacing="0" border="1" bgcolor="#eeeeee" width="100%" cellpadding="5">
    <tbody>
        <tr>
            <td><code>
            <pre class="section">	public void start(BundleContext context) throws Exception {
		Properties props = new Properties();
		props.put(&quot;ClassRoom&quot;, &quot;ClassOne&quot;);
		context.registerService(NameService.class.getName(), new NameImpl(),
				props);
	}
private static class NameImpl implements NameService {
		// The set of names contained in the arrays.
		String[] m_name = { &quot;Marry&quot;, &quot;John&quot;, &quot;David&quot;, &quot;Rachel&quot;, &quot;Ross&quot; };
		/**
		 * Implements NameService.checkName(). Determines if the passed name is
		 * contained in the Array.
		 * 
		 * @param name
		 *            the name to be checked.
		 * @return true if the name is in the Array, false otherwise.
		 */
		public boolean checkName(String name) {
			// This is very inefficient
			for (int i = 0; i &lt; m_name.length; i++) {
				if (m_name[i].equals(name)) {
					return true;
				}
			}
			return false;
		}
	} 
	</pre>
            </code></td>
        </tr>
    </tbody>
</table>
<br />
<p>在start()方法中，利用BundleContext注册一个姓名查询服务，并且为该服务设置相关属性以便服务查询。在实现姓名查询服务时，我们简单定义了一个静态数组用于存放有效的姓名信息。</p>
<p>(3)定义Bundle描述文件MANIFEST.MF，Bundle应用example的MANIFEST.MF文件如下：</p>
<br />
<a name="N1010B"><strong>MANIFEST.MF文件信息</strong></a><br />
<table cellspacing="0" border="1" bgcolor="#eeeeee" width="100%" cellpadding="5">
    <tbody>
        <tr>
            <td><code>
            <pre class="section">Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Example Bundle
Bundle-SymbolicName: example
Bundle-Version: 1.0.0
Bundle-Activator: example.osgi.Activator
Bundle-Localization: plugin
Import-Package: org.osgi.framework;version=&quot;1.3.0&quot;
Export-Package: example.service
</pre>
            </code></td>
        </tr>
    </tbody>
</table>
<br />
<p>其中，Bundle-Activator属性指明了实现BundleActivator接口的类，该类用来启动和停止Bundle应用。Export-Package属性指定了该Bundle输出的共享包，该属性可以使其他的Bundle应用引用我们所定义的服务接口。</p>
<p>(4)创建项目名为exampleClient的Bundle应用，该应用在OSGi平台上查寻并引用example Bundle应用已经注册的姓名查询服务，然后从标准输入读入用户所输入的姓名信息，判断所输入姓名是否有效。exampleClient应用的部分源代码如下，读者可从参考资料中获得完整源代码。</p>
<br />
<a name="N1011B"><strong>ExampleClient Bundle部分源代码</strong></a><br />
<table cellspacing="0" border="1" bgcolor="#eeeeee" width="100%" cellpadding="5">
    <tbody>
        <tr>
            <td><code>
            <pre class="section">	public void start(BundleContext context) throws Exception {
		ServiceReference[] refs = context.getServiceReferences(
				NameService.class.getName(), &quot;(ClassRoom=*)&quot;);
		if (refs != null) {
			try {
				System.out.println(&quot;Enter a blank line to exit.&quot;);
				BufferedReader in = new BufferedReader(new InputStreamReader(
						System.in));
				String name = &quot;&quot;;
				// Loop endlessly.
				while (true) {
					// Ask the user to enter a name.
					System.out.print(&quot;Enter a Name: &quot;);
					name = in.readLine();
					// If the user entered a blank line, then
					// exit the loop.
					if (name.length() == 0) {
						break;
					}
					// First, get a name service and then check
					// if the name is correct.
					NameService nameservice = (NameService) context
							.getService(refs[0]);
					if (nameservice.checkName(name)) {
						System.out.println(&quot;The Name is Correct.&quot;);
					} else {
						System.out.println(&quot;The Name is Incorrect.&quot;);
					}
					// Unget the name service.
					context.ungetService(refs[0]);
				}
			} catch (IOException ex) {
			}
		} else {
			System.out.println(&quot;Couldn't find any name service...&quot;);
		}
	}
	</pre>
            </code></td>
        </tr>
    </tbody>
</table>
<br />
<br />
<table cellspacing="0" border="0" width="100%" cellpadding="0">
    <tbody>
        <tr>
            <td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" alt="" width="100%" /><br />
            <img src="http://www.ibm.com/i/c.gif" border="0" height="6" alt="" width="8" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" align="right" cellpadding="0">
    <tbody>
        <tr align="right">
            <td><img src="http://www.ibm.com/i/c.gif" height="4" alt="" width="100%" /><br />
            <table cellspacing="0" border="0" cellpadding="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" alt="" width="16" /><br />
                        </td>
                        <td align="right" valign="top"><a href="http://www-128.ibm.com/developerworks/cn/opensource/os-ecl-osgibdev/index.html#main" class="fbox"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N10125"><span class="atitle">Bundle的部署及运行</span></a></p>
<p>在Eclipse平台中，选择File--&gt;Export...菜单，将开发的example和exampleClient两个Bundle应用导出成Jar文件，以便将它们部署到OSGi服务平台中。选择将要运行的Bundle应用，鼠标右键点击，在弹出菜单中，选择Run AS--&gt;Equinox FrameWork来启动OSGi服务平台。在Equinox启动配置控制台中，可以为Bundle应用设置默认的Start Level和Bundle应用是否需要自动启动等选项。在本例中，为了讲解如何安装及启动Bundle应用，只将example Bundle应用设为自动启动，而exampleClient Bundle应用需要我们用命令安装及启动。</p>
<p>当OSGi Equinox FrameWork启动后，在OSGi控制命令台中输入ss命令，可以查看OSGi服务平台中已经安装的Bundle应用信息及其状态。如图4所示，可以看到当前OSGi服务平台中有两个Bundle处于Active状态，其中，system.bundle_3.2.0.v20060328为OSGi框架的系统Bundle，而example_1.0.0为注册姓名查询服务的Bundle应用，1.0.0为Bundle应用的版本号。</p>
<br />
<a name="N10133"><strong>图示4 Bundle信息查询</strong></a><br />
<img src="http://www-128.ibm.com/developerworks/cn/opensource/os-ecl-osgibdev/images/image008.jpg" border="0" height="157" alt="图示4 Bundle信息查询" width="467" /> <br />
<p>在OSGi控制命令台中利用install命令安装exampleClient Bundle应用，用ss命令查看安装后的Bundle应用信息及其状态。如图5所示：</p>
<br />
<a name="N10148"><strong>图示5 安装Bundle</strong></a><br />
<img src="http://www-128.ibm.com/developerworks/cn/opensource/os-ecl-osgibdev/images/image010.jpg" border="0" height="195" alt="图示5 安装Bundle" width="467" /> <br />
<p>在OSGi控制命令台中利用start命令安装exampleClient Bundle应用，用户可输入姓名，利用姓名查询服务来判断所输入姓名是否有效，用ss命令查看启动后的Bundle应用信息及其状态。如图6所示：</p>
<br />
<a name="N1015D"><strong>图示6 启动Bundle</strong></a><br />
<img src="http://www-128.ibm.com/developerworks/cn/opensource/os-ecl-osgibdev/images/image012.jpg" border="0" height="284" alt="图示6 启动Bundle" width="482" /> <br />
<p>用户在在OSGi控制命令台中，可利用stop命令来停止指定的Bundle应用，close命令用来停止并退出OSGi控制命令台。关于OSGi Equinox FrameWork控制台命令的详细信息，可查看参考资料。</p>
<br />
<table cellspacing="0" border="0" width="100%" cellpadding="0">
    <tbody>
        <tr>
            <td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" alt="" width="100%" /><br />
            <img src="http://www.ibm.com/i/c.gif" border="0" height="6" alt="" width="8" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" align="right" cellpadding="0">
    <tbody>
        <tr align="right">
            <td><img src="http://www.ibm.com/i/c.gif" height="4" alt="" width="100%" /><br />
            <table cellspacing="0" border="0" cellpadding="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" alt="" width="16" /><br />
                        </td>
                        <td align="right" valign="top"><a href="http://www-128.ibm.com/developerworks/cn/opensource/os-ecl-osgibdev/index.html#main" class="fbox"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="N10170"><span class="atitle">总结</span></a></p>
<p>OSGi服务框架提供了开放的、面向服务的、易于部署的编程模型，在构件面向服务为中心的企业应用的过程中，OSGi 技术正发挥越来越重要的作用。目前，Eclipse 3.2 体系架构是参照OSGi实现的，Equinox框架是 Eclipse 组织基于OSGi Release 4 的一个实现框架，它实现了OSGi 规范的核心框架和许多标准框架服务。在本文中，我们利用Eclipse 平台开发了两个Bundle应用，并且在Bundle应用中，声明、实现、注册并引用了一个简单的服务，最后，将Bundle应用部署到Equinox OSGi服务框架中。通过本文，读者可以了解如何开发和部署基于OSGi规范的Bundle应用。</p>
<br />
<br />
<table cellspacing="0" border="0" width="100%" cellpadding="0">
    <tbody>
        <tr>
            <td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" alt="" width="100%" /><br />
            <img src="http://www.ibm.com/i/c.gif" border="0" height="6" alt="" width="8" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" align="right" cellpadding="0">
    <tbody>
        <tr align="right">
            <td><img src="http://www.ibm.com/i/c.gif" height="4" alt="" width="100%" /><br />
            <table cellspacing="0" border="0" cellpadding="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" alt="" width="16" /><br />
                        </td>
                        <td align="right" valign="top"><a href="http://www-128.ibm.com/developerworks/cn/opensource/os-ecl-osgibdev/index.html#main" class="fbox"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><span class="atitle"><a name="download">下载</a></span></p>
<table class="data-table-1" cellspacing="0" border="0" width="100%" cellpadding="0">
    <tbody>
        <tr>
            <th>名字</th>
            <th style="TEXT-ALIGN: right">大小</th>
            <th>下载方法</th>
        </tr>
        <tr>
            <td nowrap="nowrap">example.zip</td>
            <td nowrap="nowrap" style="TEXT-ALIGN: right">8KB</td>
            <td nowrap="nowrap"><a href="http://www-128.ibm.com/developerworks/cn/opensource/os-ecl-osgibdev/example.zip" class="fbox"><strong>HTTP</strong></a></td>
        </tr>
    </tbody>
</table>
<table cellspacing="0" border="0" cellpadding="0">
    <tbody>
        <tr valign="top">
            <td colspan="5"><img src="http://www.ibm.com/i/c.gif" border="0" height="12" alt="" width="12" /></td>
        </tr>
        <tr>
            <td><img src="http://www.ibm.com/i/v14/icons/fw.gif" height="16" alt="" width="16" /></td>
            <td><a href="http://www-128.ibm.com/developerworks/cn/whichmethod.html" class="fbox">关于下载方法的信息</a></td>
            <td><img src="http://www.ibm.com/i/c.gif" height="1" alt="" width="50" /></td>
            <td><img src="http://www.ibm.com/i/v14/icons/sout.gif" height="16" alt="" width="16" /></td>
            <td><a href="http://www.adobe.com/products/acrobat/readstep2.html" class="fbox">Get Adobe&reg; Reader&reg;</a></td>
        </tr>
    </tbody>
</table>
<br />
<table cellspacing="0" border="0" width="100%" cellpadding="0">
    <tbody>
        <tr>
            <td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" alt="" width="100%" /><br />
            <img src="http://www.ibm.com/i/c.gif" border="0" height="6" alt="" width="8" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" align="right" cellpadding="0">
    <tbody>
        <tr align="right">
            <td><img src="http://www.ibm.com/i/c.gif" height="4" alt="" width="100%" /><br />
            <table cellspacing="0" border="0" cellpadding="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" alt="" width="16" /><br />
                        </td>
                        <td align="right" valign="top"><a href="http://www-128.ibm.com/developerworks/cn/opensource/os-ecl-osgibdev/index.html#main" class="fbox"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="resources"><span class="atitle">参考资料 </span></a></p>
<ul>
    <li>OSGi Alliance。 <a href="http://www.osgi.org/">http://www.osgi.org/</a>。包含了OSGi Release 4的最新规范等信息。<br />
    <br />
    </li>
    <li>在 <a href="http://www.eclipse.org/">Eclipse.org</a> 中获得有关 Eclipse和Equinox的更多详细资料。<br />
    </li>
</ul>
<br />
<table cellspacing="0" border="0" width="100%" cellpadding="0">
    <tbody>
        <tr>
            <td><img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" height="1" alt="" width="100%" /><br />
            <img src="http://www.ibm.com/i/c.gif" border="0" height="6" alt="" width="8" /></td>
        </tr>
    </tbody>
</table>
<table class="no-print" cellspacing="0" align="right" cellpadding="0">
    <tbody>
        <tr align="right">
            <td><img src="http://www.ibm.com/i/c.gif" height="4" alt="" width="100%" /><br />
            <table cellspacing="0" border="0" cellpadding="0">
                <tbody>
                    <tr>
                        <td valign="middle"><img src="http://www.ibm.com/i/v14/icons/u_bold.gif" border="0" height="16" alt="" width="16" /><br />
                        </td>
                        <td align="right" valign="top"><a href="http://www-128.ibm.com/developerworks/cn/opensource/os-ecl-osgibdev/index.html#main" class="fbox"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="author"><span class="atitle">关于作者</span></a></p>
<table cellspacing="0" border="0" width="100%" cellpadding="0">
    <tbody>
        <tr>
            <td colspan="3"><img src="http://www.ibm.com/i/c.gif" height="5" alt="" width="100%" /></td>
        </tr>
        <tr align="left" valign="top">
            <td>
            <p>&nbsp;</p>
            </td>
            <td><img src="http://www.ibm.com/i/c.gif" height="5" alt="" width="4" /></td>
            <td width="100%">
            <p>杨晓飞：目前在IBM中国软件开发试验室工作。软件工程师。 是WebSphere Portal 和Integrated Solutions Console Team的成员， 专注于Portal, Application Server, Integrated Solutons Console的研究。对企业自主运算(Autonomic Computing)，J2EE，SOA, OSGi 等有浓厚兴趣。E-mail: <a href="mailto:yangxiaofei2000@hotmail.com?cc=">yangxiaofei2000@hotmail.com</a>。</p>
            </td>
        </tr>
    </tbody>
</table>
          <br/>
          <span style="color:red;">
            <a href="http://kapokfly.javaeye.com/blog/43074#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 04 Jan 2007 20:03:35 +0800</pubDate>
        <link>http://kapokfly.javaeye.com/blog/43074</link>
        <guid>http://kapokfly.javaeye.com/blog/43074</guid>
      </item>
      <item>
        <title>IAdaptable是什么？</title>
        <author>kapok_fly</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://kapokfly.javaeye.com">kapok_fly</a>&nbsp;
          链接：<a href="http://kapokfly.javaeye.com/blog/43031" style="color:red;">http://kapokfly.javaeye.com/blog/43031</a>&nbsp;
          发表时间: 2007年01月04日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div class="postText">
<p>[八进制]翻译原文地址: <font face="Arial"><a href="http://bjzhanghao.cnblogs.com/archive/2005/09/24/243312.html">http://bjzhanghao.cnblogs.com/archive/2005/09/24/243312.html</a></font></p>
<p>原文地址：<a href="http://www.eclipsezone.com/articles/what-is-iadaptable/">http://www.eclipsezone.com/articles/what-is-iadaptable/</a></p>
<p><a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/core/runtime/IAdaptable.html">IAdaptable</a>在Eclipse里是一个非常重要的接口。对于Eclipse开发老手来说，它就像异常处理和抽象类一样寻常；但是对新手而言，它却令人感到困惑和畏惧。这篇文章将向你解释IAdaptable到底是什么，以及它在Eclipse里起到的作用。</p>
<h3>类型转换</h3>
<p>Java是所谓的强类型语言，也就是说，每个实例都对应一个类型。其实类型分为两种：声明类型和运行时类型（也分别被称为静态类型和动态类型）。像Python这样的弱类型语言常被称为无类型的语言，其实严格说来不是这样，因为每个实例都对应一个运行时类型，只是你并不需要声明这一点而已。</p>
<p>现在回到Java，为了能够执行一个类的某个方法，这个方法必须在声明类型中可见，换句话说，即使在运行时实例是某个子类型，你也只能执行那些父类型里定义的方法。</p>
<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" /><span style="COLOR: #000000">List&nbsp;list&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;ArrayList(); <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" />list.add(</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">data</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;正确，add是List里定义的方法</span><span style="COLOR: #008000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" /></span><span style="COLOR: #000000">list.ensureCapacity(</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;不正确，ensureCapacity()只在ArrayList被定义 <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" /></span> </div>
<p>如果一定要执行特定类型的方法，我们必须先强制转换这个实例到正确的类型。对于上面的例子，我们可以将list转换为ArrayList（译注：原文In this case, we can cast ArrayList to List，怀疑是笔误），因为ArrayList实现了List接口，你甚至可以在运行时通过instanceof关键字检验list是否为ArrayList的一个实例。</p>
<h3>可扩展的接口</h3>
<p>不幸的是，一个类可能并没有实现你需要的接口，这样就无法进行强制类型转换了。原因有很多，比如只在少数情况下才需要这个接口，或者你需要的接口是在另一个不相关的库里，又或者接口是有了类以后才开发出来的，等等。</p>
<p>这时你就需要IAdaptable了。可以把IAdaptable想象为一个能够动态进行类型转换的途径。对比下面的直接类型转换：</p>
<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" /><span style="COLOR: #000000">Object&nbsp;o&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;ArrayList(); <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" />List&nbsp;list&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(List)o; <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" /></span> </div>
<p>换一种方式，我们可以这样做：</p>
<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" /><span style="COLOR: #000000">IAdaptable&nbsp;adaptable&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;ArrayList();</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">译注：这里的ArrayList应该不是指java.util.ArrayList</span><span style="COLOR: #008000"> <font color="#ff0000">笨笨注: 这里应的ArrayList应该是一个实现了IAdaptable接口的自定义类, 这个类'<font style="BACKGROUND-COLOR: #ffff00">兼容</font>'java.util.List</font><br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" /></span><span style="COLOR: #000000">List&nbsp;list&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(List)adaptable.getAdapter(java.util.List.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">); <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" /></span> </div>
<p>这就是上面所说的动态类型转换，我们所做的事情是试图把adaptable转换为一个List实例。</p>
<p>那么，当可以直接转换的时候为什么要费这个力气通过getAdapter()来转换呢？其实这种机制可以让我们将目标类转换为它并没有实现的接口。举个例子，我们可能想把一个HashMap当作List来用，尽管这两个类的性质并不相同，可以这么做：</p>
<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" /><span style="COLOR: #000000">IAdaptable&nbsp;adaptable&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;HashMap();</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">译注：这里的HashMap应该不是指java.util.HashMap</span><span style="COLOR: #008000">&nbsp;<span style="COLOR: #008000">&nbsp;<font color="#ff0000">笨笨注: 这里应的HashMap应该是一个实现了IAdaptable接口的自定义类, 这个类'<font style="BACKGROUND-COLOR: #ffff00">兼容</font>'java.util.List</font></span><br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" /></span><span style="COLOR: #000000">List&nbsp;list&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(List)adaptable.getAdapter(java.util.List.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">); <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" /></span> </div>
<h3>实现IAdaptable接口</h3>
<p>大部分IAdaptable的实现是一些if语句的叠加，比如我们现在要实现HashMap的getAdapter()方法，它看起来可能是这样：</p>
<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" id="Codehighlighter1_43_263_Open_Image" onclick="this.style.display='none'; Codehighlighter1_43_263_Open_Text.style.display='none'; Codehighlighter1_43_263_Closed_Image.style.display='inline'; Codehighlighter1_43_263_Closed_Text.style.display='inline';" height="16" align="top" alt="" width="11" /><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" id="Codehighlighter1_43_263_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_43_263_Closed_Text.style.display='none'; Codehighlighter1_43_263_Open_Image.style.display='inline'; Codehighlighter1_43_263_Open_Text.style.display='inline';" height="16" align="top" alt="" style="DISPLAY: none" width="11" /><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;HashMap&nbsp;</span><span style="COLOR: #0000ff">implements</span><span style="COLOR: #000000">&nbsp;IAdaptable&nbsp;</span><span id="Codehighlighter1_43_263_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://bjzhanghao.cnblogs.com/Images/dot.gif" height="20" alt="" width="15" /></span><span id="Codehighlighter1_43_263_Open_Text"><span style="COLOR: #000000">{ <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" id="Codehighlighter1_85_252_Open_Image" onclick="this.style.display='none'; Codehighlighter1_85_252_Open_Text.style.display='none'; Codehighlighter1_85_252_Closed_Image.style.display='inline'; Codehighlighter1_85_252_Closed_Text.style.display='inline';" height="16" align="top" alt="" width="11" /><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" id="Codehighlighter1_85_252_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_85_252_Closed_Text.style.display='none'; Codehighlighter1_85_252_Open_Image.style.display='inline'; Codehighlighter1_85_252_Open_Text.style.display='inline';" height="16" align="top" alt="" style="DISPLAY: none" width="11" />&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Object&nbsp;getAdapter(Class&nbsp;clazz)&nbsp;</span><span id="Codehighlighter1_85_252_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://bjzhanghao.cnblogs.com/Images/dot.gif" height="20" alt="" width="15" /></span><span id="Codehighlighter1_85_252_Open_Text"><span style="COLOR: #000000">{ <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" id="Codehighlighter1_126_231_Open_Image" onclick="this.style.display='none'; Codehighlighter1_126_231_Open_Text.style.display='none'; Codehighlighter1_126_231_Closed_Image.style.display='inline'; Codehighlighter1_126_231_Closed_Text.style.display='inline';" height="16" align="top" alt="" width="11" /><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" id="Codehighlighter1_126_231_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_126_231_Closed_Text.style.display='none'; Codehighlighter1_126_231_Open_Image.style.display='inline'; Codehighlighter1_126_231_Open_Text.style.display='inline';" height="16" align="top" alt="" style="DISPLAY: none" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(clazz&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;java.util.List.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">)&nbsp;</span><span id="Codehighlighter1_126_231_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://bjzhanghao.cnblogs.com/Images/dot.gif" height="20" alt="" width="15" /></span><span id="Codehighlighter1_126_231_Open_Text"><span style="COLOR: #000000">{ <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/InBlock.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&nbsp;list&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;ArrayList(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.size()); <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/InBlock.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.addAll(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.values()); <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/InBlock.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;list; <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/InBlock.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">; <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/InBlock.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;<img src="http://bjzhanghao.cnblogs.com/Images/dot.gif" height="20" alt="" width="15" /></span><span style="COLOR: #008000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" height="16" align="top" alt="" width="11" /></span><span style="COLOR: #000000">}</span></span><span style="COLOR: #000000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" /></span> </div>
<p>所做的就是返回一个适配器（adapter，更确切的说是一个副本），而不是进行直接的类型转换。如果参数类型没有被支持，惯例是返回null值（而非抛出异常），代表这个方法失败了。因此，在调用这个方法时，不应该假定它总是返回非null值。</p>
<h3>PlatformObject</h3>
<p>当然，如果你希望增加一个新的被支持的adapter类型时必须编辑这个类才行（译注：在getAdapter()里增加更多的if语句），这会比较辛苦。而且，既然你已经知道了这个类型，何不直接修改接口声明呢？其实有很多原因使得你并不希望直接编辑这个类（例如更容易保持向下兼容性），也不想改变它的类型（HashMap虽然不是一个List，但可以转换过去）。</p>
<p>Eclipse通过PlatformObject抽象类来解决以上问题，它为你实现了IAdaptable接口，Eclipse平台（Platform）提供了IAdapterManager的一个实现，并且可以通过Platform.getAdapterManager()访问到，它把所有对getAdapter()的请求（调用）委托给一个名为IAdapterManager的东西。你可以将它想象为一个巨大的保存着类和adapter信息的Map，而PlatformObject的getAdapter()方法会查找这个Map。</p>
<h3>适配已存在的类</h3>
<p>这样，PlatformObject不需要重新编译就能够支持新的adapter类型，这一点在Eclipse里被大量使用以支持workspace的扩展点。</p>
<p>现在假设我们想要将一个只包含String类型元素的List转换为一个XMl节点，这个节点的格式如下：</p>
<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" /><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">List</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">Entry</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">First&nbsp;String</span><span style="COLOR: #000000"><span style="COLOR: #000000">Entry</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">Entry</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">Second&nbsp;String</span><span style="COLOR: #000000"><span style="COLOR: #000000">Entry</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">Entry</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">Third&nbsp;String</span><span style="COLOR: #000000"><span style="COLOR: #000000">Entry</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" /></span><span style="COLOR: #000000"><span style="COLOR: #000000">List</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" /></span> </span></span></span></span></div>
<p>因为toString()方法可能有其他用途，我们不能通过覆盖toString()方法来实现这个功能。所以，我们要给List关联一个工厂类以处理XML节点类型的适配请求。要管理工厂类需要以下三个步骤：</p>
<p>1、由List生成一个Node，我们把这个转换过程用IAdapterFactory包装起来：</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" /><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;nu.xom.</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">; <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" id="Codehighlighter1_73_644_Open_Image" onclick="this.style.display='none'; Codehighlighter1_73_644_Open_Text.style.display='none'; Codehighlighter1_73_644_Closed_Image.style.display='inline'; Codehighlighter1_73_644_Closed_Text.style.display='inline';" height="16" align="top" alt="" width="11" /><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" id="Codehighlighter1_73_644_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_73_644_Closed_Text.style.display='none'; Codehighlighter1_73_644_Open_Image.style.display='inline'; Codehighlighter1_73_644_Open_Text.style.display='inline';" height="16" align="top" alt="" style="DISPLAY: none" width="11" /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;NodeListFactory&nbsp;</span><span style="COLOR: #0000ff">implements</span><span style="COLOR: #000000">&nbsp;IAdapterFactory&nbsp;</span><span id="Codehighlighter1_73_644_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://bjzhanghao.cnblogs.com/Images/dot.gif" height="20" alt="" width="15" /></span><span id="Codehighlighter1_73_644_Open_Text"><span style="COLOR: #000000">{ <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" id="Codehighlighter1_77_90_Open_Image" onclick="this.style.display='none'; Codehighlighter1_77_90_Open_Text.style.display='none'; Codehighlighter1_77_90_Closed_Image.style.display='inline'; Codehighlighter1_77_90_Closed_Text.style.display='inline';" height="16" align="top" alt="" width="11" /><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" id="Codehighlighter1_77_90_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_77_90_Closed_Text.style.display='none'; Codehighlighter1_77_90_Open_Image.style.display='inline'; Codehighlighter1_77_90_Open_Text.style.display='inline';" height="16" align="top" alt="" style="DISPLAY: none" width="11" />&nbsp;&nbsp;</span><span id="Codehighlighter1_77_90_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id="Codehighlighter1_77_90_Open_Text"><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;可以转换到的类型&nbsp;</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" id="Codehighlighter1_131_151_Open_Image" onclick="this.style.display='none'; Codehighlighter1_131_151_Open_Text.style.display='none'; Codehighlighter1_131_151_Closed_Image.style.display='inline'; Codehighlighter1_131_151_Closed_Text.style.display='inline';" height="16" align="top" alt="" width="11" /><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" id="Codehighlighter1_131_151_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_131_151_Closed_Text.style.display='none'; Codehighlighter1_131_151_Open_Image.style.display='inline'; Codehighlighter1_131_151_Open_Text.style.display='inline';" height="16" align="top" alt="" style="DISPLAY: none" width="11" />&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">final</span><span style="COLOR: #000000">&nbsp;Class[]&nbsp;types&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span id="Codehighlighter1_131_151_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://bjzhanghao.cnblogs.com/Images/dot.gif" height="20" alt="" width="15" /></span><span id="Codehighlighter1_131_151_Open_Text"><span style="COLOR: #000000">{ <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/InBlock.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;Node.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">, <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">; <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" id="Codehighlighter1_188_210_Open_Image" onclick="this.style.display='none'; Codehighlighter1_188_210_Open_Text.style.display='none'; Codehighlighter1_188_210_Closed_Image.style.display='inline'; Codehighlighter1_188_210_Closed_Text.style.display='inline';" height="16" align="top" alt="" width="11" /><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" id="Codehighlighter1_188_210_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_188_210_Closed_Text.style.display='none'; Codehighlighter1_188_210_Open_Image.style.display='inline'; Codehighlighter1_188_210_Open_Text.style.display='inline';" height="16" align="top" alt="" style="DISPLAY: none" width="11" />&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Class[]&nbsp;getAdapterList()&nbsp;</span><span id="Codehighlighter1_188_210_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://bjzhanghao.cnblogs.com/Images/dot.gif" height="20" alt="" width="15" /></span><span id="Codehighlighter1_188_210_Open_Text"><span style="COLOR: #000000">{ <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/InBlock.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;types; <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" id="Codehighlighter1_214_231_Open_Image" onclick="this.style.display='none'; Codehighlighter1_214_231_Open_Text.style.display='none'; Codehighlighter1_214_231_Closed_Image.style.display='inline'; Codehighlighter1_214_231_Closed_Text.style.display='inline';" height="16" align="top" alt="" width="11" /><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" id="Codehighlighter1_214_231_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_214_231_Closed_Text.style.display='none'; Codehighlighter1_214_231_Open_Image.style.display='inline'; Codehighlighter1_214_231_Open_Text.style.display='inline';" height="16" align="top" alt="" style="DISPLAY: none" width="11" />&nbsp;&nbsp;</span><span id="Codehighlighter1_214_231_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</span><span id="Codehighlighter1_214_231_Open_Text"><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;转换到Node的功能代码&nbsp;</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" id="Codehighlighter1_286_642_Open_Image" onclick="this.style.display='none'; Codehighlighter1_286_642_Open_Text.style.display='none'; Codehighlighter1_286_642_Closed_Image.style.display='inline'; Codehighlighter1_286_642_Closed_Text.style.display='inline';" height="16" align="top" alt="" width="11" /><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" id="Codehighlighter1_286_642_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_286_642_Closed_Text.style.display='none'; Codehighlighter1_286_642_Open_Image.style.display='inline'; Codehighlighter1_286_642_Open_Text.style.display='inline';" height="16" align="top" alt="" style="DISPLAY: none" width="11" />&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Object&nbsp;getAdapter(Object&nbsp;list,&nbsp;Class&nbsp;clazz)&nbsp;</span><span id="Codehighlighter1_286_642_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://bjzhanghao.cnblogs.com/Images/dot.gif" height="20" alt="" width="15" /></span><span id="Codehighlighter1_286_642_Open_Text"><span style="COLOR: #000000">{ <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" id="Codehighlighter1_341_606_Open_Image" onclick="this.style.display='none'; Codehighlighter1_341_606_Open_Text.style.display='none'; Codehighlighter1_341_606_Closed_Image.style.display='inline'; Codehighlighter1_341_606_Closed_Text.style.display='inline';" height="16" align="top" alt="" width="11" /><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" id="Codehighlighter1_341_606_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_341_606_Closed_Text.style.display='none'; Codehighlighter1_341_606_Open_Image.style.display='inline'; Codehighlighter1_341_606_Open_Text.style.display='inline';" height="16" align="top" alt="" style="DISPLAY: none" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(clazz&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;Node.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;&amp;</span><span style="COLOR: #000000">&nbsp;list&nbsp;</span><span style="COLOR: #0000ff">instanceof</span><span style="COLOR: #000000">&nbsp;List)&nbsp;</span><span id="Codehighlighter1_341_606_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://bjzhanghao.cnblogs.com/Images/dot.gif" height="20" alt="" width="15" /></span><span id="Codehighlighter1_341_606_Open_Text"><span style="COLOR: #000000">{ <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/InBlock.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Element&nbsp;root&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Element(</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">List</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">); <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/InBlock.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator&nbsp;it&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;list.iterator(); <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" id="Codehighlighter1_448_581_Open_Image" onclick="this.style.display='none'; Codehighlighter1_448_581_Open_Text.style.display='none'; Codehighlighter1_448_581_Closed_Image.style.display='inline'; Codehighlighter1_448_581_Closed_Text.style.display='inline';" height="16" align="top" alt="" width="11" /><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" id="Codehighlighter1_448_581_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_448_581_Closed_Text.style.display='none'; Codehighlighter1_448_581_Open_Image.style.display='inline'; Codehighlighter1_448_581_Open_Text.style.display='inline';" height="16" align="top" alt="" style="DISPLAY: none" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(it.hasNext())&nbsp;</span><span id="Codehighlighter1_448_581_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://bjzhanghao.cnblogs.com/Images/dot.gif" height="20" alt="" width="15" /></span><span id="Codehighlighter1_448_581_Open_Text"><span style="COLOR: #000000">{ <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/InBlock.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Element&nbsp;item&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Element(</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">Entry</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">); <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/InBlock.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item.appendChild(it.next().toString()); <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/InBlock.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;root.appendChild(item); <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/InBlock.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;root; <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" id="Codehighlighter1_613_638_Open_Image" onclick="this.style.display='none'; Codehighlighter1_613_638_Open_Text.style.display='none'; Codehighlighter1_613_638_Closed_Image.style.display='inline'; Codehighlighter1_613_638_Closed_Text.style.display='inline';" height="16" align="top" alt="" width="11" /><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" id="Codehighlighter1_613_638_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_613_638_Closed_Text.style.display='none'; Codehighlighter1_613_638_Open_Image.style.display='inline'; Codehighlighter1_613_638_Open_Text.style.display='inline';" height="16" align="top" alt="" style="DISPLAY: none" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000">&nbsp;</span><span id="Codehighlighter1_613_638_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://bjzhanghao.cnblogs.com/Images/dot.gif" height="20" alt="" width="15" /></span><span id="Codehighlighter1_613_638_Open_Text"><span style="COLOR: #000000">{ <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/InBlock.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">; <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" height="16" align="top" alt="" width="11" />}</span></span><span style="COLOR: #000000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" /></span> </div>
<p>2、把这个工厂类注册到Platform的AdapterManager，这样当我们希望从List的实例中获得一个Node实例时，就会找到我们的工厂类。注册一个工厂类的方式也很简单：</p>
<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" /><span style="COLOR: #000000">Platform.getAdapterManager().registerAdapters( <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;NodeListFactory(),&nbsp;List.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" />); <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" /></span> </div>
<p>这条语句将NodeListFactory关联到List类型。当从List里请求adapter时，Platform的AdapterManager会找到NodeListFactory，因为在后者的getAdapterList()方法的返回结果里包含了Node类，所以它知道从List实例得到一个Node实例是可行的。在Eclipse里，这个注册步骤一般是在plugin启动时完成的，但也可以通过org.eclipse.core.runtime.adapters扩展点来完成。</p>
<p>3、从List获得Node，下面是例子代码:</p>
<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" id="Codehighlighter1_34_182_Open_Image" onclick="this.style.display='none'; Codehighlighter1_34_182_Open_Text.style.display='none'; Codehighlighter1_34_182_Closed_Image.style.display='inline'; Codehighlighter1_34_182_Closed_Text.style.display='inline';" height="16" align="top" alt="" width="11" /><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" id="Codehighlighter1_34_182_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_34_182_Closed_Text.style.display='none'; Codehighlighter1_34_182_Open_Image.style.display='inline'; Codehighlighter1_34_182_Open_Text.style.display='inline';" height="16" align="top" alt="" style="DISPLAY: none" width="11" /><span style="COLOR: #000000">Node&nbsp;getNodeFrom(IAdaptable&nbsp;list)&nbsp;</span><span id="Codehighlighter1_34_182_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://bjzhanghao.cnblogs.com/Images/dot.gif" height="20" alt="" width="15" /></span><span id="Codehighlighter1_34_182_Open_Text"><span style="COLOR: #000000">{ <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/InBlock.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;Object&nbsp;adaptable&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;list.getAdapter(Node.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">); <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" id="Codehighlighter1_111_165_Open_Image" onclick="this.style.display='none'; Codehighlighter1_111_165_Open_Text.style.display='none'; Codehighlighter1_111_165_Closed_Image.style.display='inline'; Codehighlighter1_111_165_Closed_Text.style.display='inline';" height="16" align="top" alt="" width="11" /><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" id="Codehighlighter1_111_165_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_111_165_Closed_Text.style.display='none'; Codehighlighter1_111_165_Open_Image.style.display='inline'; Codehighlighter1_111_165_Open_Text.style.display='inline';" height="16" align="top" alt="" style="DISPLAY: none" width="11" />&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(adaptable&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">)&nbsp;</span><span id="Codehighlighter1_111_165_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://bjzhanghao.cnblogs.com/Images/dot.gif" height="20" alt="" width="15" /></span><span id="Codehighlighter1_111_165_Open_Text"><span style="COLOR: #000000">{ <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/InBlock.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;Node&nbsp;node&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(Node)adaptable; <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/InBlock.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;node; <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/InBlock.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">; <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" height="16" align="top" alt="" width="11" />}</span></span><span style="COLOR: #000000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" /></span> </div>
<h3>总结</h3>
<p>综上所述，要在运行时为一个已有的类增加功能，所要做的只是定义一个用来转换的工厂类，然后把它注册到Platform的AdapterManager即可。这种方式在保持UI组件和非UI组件的分离方面特别有用。例如在org.rcpapps.rcpnews.ui和org.rcpapps.rcpnews这两个plugin里，前者的IPropertySource需要与后者的数据对象（data object）相关联，当前者初始化时，它将IPropertySource注册到Platform，当数据对象在导航器（navigator）里被选中的时候，属性视图里就会显示正确的属性。</p>
<p>显然，java.util.List并不是PlatformObject的子类，所以如果你希望能够编译这里所说的例子，必须建立一个List的子类型。注意，可以直接实现IAdaptable接口，而非必须继承PlatformObject抽象类。</p>
<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" id="Codehighlighter1_55_279_Open_Image" onclick="this.style.display='none'; Codehighlighter1_55_279_Open_Text.style.display='none'; Codehighlighter1_55_279_Closed_Image.style.display='inline'; Codehighlighter1_55_279_Closed_Text.style.display='inline';" height="16" align="top" alt="" width="11" /><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" id="Codehighlighter1_55_279_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_55_279_Closed_Text.style.display='none'; Codehighlighter1_55_279_Open_Image.style.display='inline'; Codehighlighter1_55_279_Open_Text.style.display='inline';" height="16" align="top" alt="" style="DISPLAY: none" width="11" /><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;AdaptableList&nbsp;</span><span style="COLOR: #0000ff">implements</span><span style="COLOR: #000000">&nbsp;IAdaptable,&nbsp;List&nbsp;</span><span id="Codehighlighter1_55_279_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://bjzhanghao.cnblogs.com/Images/dot.gif" height="20" alt="" width="15" /></span><span id="Codehighlighter1_55_279_Open_Text"><span style="COLOR: #000000">{ <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" id="Codehighlighter1_99_171_Open_Image" onclick="this.style.display='none'; Codehighlighter1_99_171_Open_Text.style.display='none'; Codehighlighter1_99_171_Closed_Image.style.display='inline'; Codehighlighter1_99_171_Closed_Text.style.display='inline';" height="16" align="top" alt="" width="11" /><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" id="Codehighlighter1_99_171_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_99_171_Closed_Text.style.display='none'; Codehighlighter1_99_171_Open_Image.style.display='inline'; Codehighlighter1_99_171_Open_Text.style.display='inline';" height="16" align="top" alt="" style="DISPLAY: none" width="11" />&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Object&nbsp;getAdapter(Class&nbsp;adapter)&nbsp;</span><span id="Codehighlighter1_99_171_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://bjzhanghao.cnblogs.com/Images/dot.gif" height="20" alt="" width="15" /></span><span id="Codehighlighter1_99_171_Open_Text"><span style="COLOR: #000000">{ <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/InBlock.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;Platform.getAdapterManager().getAdapter(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">,&nbsp;adapter); <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/InBlock.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;List&nbsp;delegate&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;ArrayList(); <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" id="Codehighlighter1_236_268_Open_Image" onclick="this.style.display='none'; Codehighlighter1_236_268_Open_Text.style.display='none'; Codehighlighter1_236_268_Closed_Image.style.display='inline'; Codehighlighter1_236_268_Closed_Text.style.display='inline';" height="16" align="top" alt="" width="11" /><img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" id="Codehighlighter1_236_268_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_236_268_Closed_Text.style.display='none'; Codehighlighter1_236_268_Open_Image.style.display='inline'; Codehighlighter1_236_268_Open_Text.style.display='inline';" height="16" align="top" alt="" style="DISPLAY: none" width="11" />&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;size()&nbsp;</span><span id="Codehighlighter1_236_268_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://bjzhanghao.cnblogs.com/Images/dot.gif" height="20" alt="" width="15" /></span><span id="Codehighlighter1_236_268_Open_Text"><span style="COLOR: #000000">{ <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/InBlock.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;delegate.size(); <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/InBlock.gif" height="16" align="top" alt="" width="11" />&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;<img src="http://bjzhanghao.cnblogs.com/Images/dot.gif" height="20" alt="" width="15" /></span><span style="COLOR: #008000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" height="16" align="top" alt="" width="11" /></span><span style="COLOR: #000000">}</span></span><span style="COLOR: #000000"> <br />
<img src="http://bjzhanghao.cnblogs.com/Images/OutliningIndicators/None.gif" height="16" align="top" alt="" width="11" /></span> </div>
<p>最后，例子里生成XML的部分使用了<a href="http://www.xom.nu/">XOM</a>的类库.</p>
</div>
          <br/>
          <span style="color:red;">
            <a href="http://kapokfly.javaeye.com/blog/43031#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 04 Jan 2007 16:22:31 +0800</pubDate>
        <link>http://kapokfly.javaeye.com/blog/43031</link>
        <guid>http://kapokfly.javaeye.com/blog/43031</guid>
      </item>
  </channel>
</rss>