﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-Dreava</title><link>http://www.blogjava.net/benniaolk/</link><description>梦幻瓜哇国</description><language>zh-cn</language><lastBuildDate>Tue, 05 May 2026 05:23:07 GMT</lastBuildDate><pubDate>Tue, 05 May 2026 05:23:07 GMT</pubDate><ttl>60</ttl><item><title>Spring DM的开发示例</title><link>http://www.blogjava.net/benniaolk/articles/316756.html</link><dc:creator>Dreava</dc:creator><author>Dreava</author><pubDate>Sun, 28 Mar 2010 09:36:00 GMT</pubDate><guid>http://www.blogjava.net/benniaolk/articles/316756.html</guid><wfw:comment>http://www.blogjava.net/benniaolk/comments/316756.html</wfw:comment><comments>http://www.blogjava.net/benniaolk/articles/316756.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.blogjava.net/benniaolk/comments/commentRss/316756.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/benniaolk/services/trackbacks/316756.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在读本文之前，您应该对基于Equinox的开发有一定的了解，如果您还不太清楚，请参考<a class="postTitle2" id="homepage1_HomePageDays_DaysList_ctl00_DayItem_DayList_ctl00_TitleUrl" href="http://www.blogjava.net/benniaolk/articles/316755.html">基于Equinox开发HelloWorld</a>一文。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;本文讲到的例子是仿照网上甚为流行的一个例子，但苦于一直未找到源码，网上贴的都是一些转帖，代码片段，估计初学者很难将其还原并调通！我最开始弄这个咚咚的时候，其过程之痛苦，难以言喻，所以想着仿照该例子的设计，给予实现，文后贴出源码，希望能帮到大家。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;该例子是一个关于计算器的实例，osgi.example.compute bundle(下文简称compute bundle)提供了统一的计算接口：Compute，另外两个bundle分别为osgi.example.compute.add(下文简称add bundle)和osgi.example.compute.multiply(下文简称multiply bundle)，在这两个bundle中，各自对compute bundle进行不同的实现，一个实现加法，一个实现乘法。另外还有一个服务消费者osgi.example.compute.consumer bundle(下文简称consumer bundle)，consumer bundle负责消费add bundle和multiply bundle提供的服务。上述4个bundle之间的关系如下图所示：<br />
<img height="345" alt="" src="http://www.blogjava.net/images/blogjava_net/benniaolk/OSGi/Spring与OSGi的整合/8.png" width="345" border="0" /></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 创建4个bundle之后的工程目录如下图所示：</p>
<p align="left"><img height="70" alt="" src="http://www.blogjava.net/images/blogjava_net/benniaolk/OSGi/Spring与OSGi的整合/9.png" width="205" border="0" /><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;通过该示例，将演示如何利用Spring DM发布和调用OSGi服务，同时还将演示OSGi的动态服务调用能力。<br />
<br />
<strong>1.&nbsp;&nbsp; bundle osgi.example.compute&nbsp;<br />
</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; compute bundle只提供一个接口——Compute，因此无需依赖更多的bundle，只需最基本的osgi即可。因为不涉及注册资源之类的，所以也无需Activator入口类。<br />
Computer接口源代码如下所示：</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://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">package</span><span style="color: #000000">&nbsp;osgi.example.compute;&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;<br />
<img id="Codehighlighter1_61_114_Open_Image" onclick="this.style.display='none'; Codehighlighter1_61_114_Open_Text.style.display='none'; Codehighlighter1_61_114_Closed_Image.style.display='inline'; Codehighlighter1_61_114_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_61_114_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_61_114_Closed_Text.style.display='none'; Codehighlighter1_61_114_Open_Image.style.display='inline'; Codehighlighter1_61_114_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">interface</span><span style="color: #000000">&nbsp;Compute&nbsp;</span><span id="Codehighlighter1_61_114_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://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_61_114_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;String&nbsp;computeNums(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;x,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;y);&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000">&nbsp;&nbsp;</span></div>
<br />
<strong>2.&nbsp;&nbsp;&nbsp; bundle osgi.example.compute.add<br />
</strong>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; add bundle是对compute bundle的具体服务实现，在MANIFEST.MF文件需要引入osgi.example.compute包；当然也可以通过添加依赖bundle的形式，即不引入包，而直接在Required Plug-ins中添加compute bundle。如下图所示：</p>
<img height="439" alt="" src="http://www.blogjava.net/images/blogjava_net/benniaolk/OSGi/Spring与OSGi的整合/10.png" width="623" border="0" /><br />
<p style="margin: 0cm 0cm 0pt; text-align: left"><span style="font-size: small"></p>
<div style="border-right: #666666 1px solid; border-top: #666666 1px solid; border-left: #666666 1px solid; width: 887px; border-bottom: #666666 1px solid; height: 1px">
<p style="margin: 0cm 0cm 0pt; text-align: left"><span style="font-size: small"><strong>注意：<span style="color: #ff0000"><span style="font-family: Calibri">OSGi</span></span>官方指出，当需要用到其他<span style="color: #ff0000"><span style="font-family: Calibri">bundle</span></span>的类型时，不提倡依赖<span style="color: #ff0000"><span style="font-family: Calibri">bundle</span></span>，应该尽可能采用<span style="color: #ff0000"><span style="font-family: Calibri">Import-package</span></span>的方式引入包，因为依赖<span style="color: #ff0000"><span style="font-family: Calibri">bundle</span></span>可能在加载<span style="color: #ff0000"><span style="font-family: Calibri">bundle</span></span>的时候发生问题。</strong></span></p>
</div>
<br />
add bundle的工程结构如下图所示：<br />
<img height="225" alt="" src="http://www.blogjava.net/images/blogjava_net/benniaolk/OSGi/Spring与OSGi的整合/11.png" width="323" border="0" /><br />
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 通过引入osgi.example.compute包，osgi.example.compute&nbsp; bundle被加到了add bundl的classpath当中，解决了开发时期的类型识别问题。<br />
这样一来，在add bundle中就能使用compute bundle中的接口了，Computer接口的实现如下：</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://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">package</span><span style="color: #000000">&nbsp;osgi.example.compute.add;&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;osgi.example.compute.Compute;&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;<br />
<img id="Codehighlighter1_119_301_Open_Image" onclick="this.style.display='none'; Codehighlighter1_119_301_Open_Text.style.display='none'; Codehighlighter1_119_301_Closed_Image.style.display='inline'; Codehighlighter1_119_301_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_119_301_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_119_301_Closed_Text.style.display='none'; Codehighlighter1_119_301_Open_Image.style.display='inline'; Codehighlighter1_119_301_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Add&nbsp;</span><span style="color: #0000ff">implements</span><span style="color: #000000">&nbsp;Compute&nbsp;</span><span id="Codehighlighter1_119_301_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://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_119_301_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;<br />
<img id="Codehighlighter1_171_296_Open_Image" onclick="this.style.display='none'; Codehighlighter1_171_296_Open_Text.style.display='none'; Codehighlighter1_171_296_Closed_Image.style.display='inline'; Codehighlighter1_171_296_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_171_296_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_171_296_Closed_Text.style.display='none'; Codehighlighter1_171_296_Open_Image.style.display='inline'; Codehighlighter1_171_296_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;String&nbsp;computeNums(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;x,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;y)&nbsp;</span><span id="Codehighlighter1_171_296_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://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_171_296_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;s&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;x&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;y;&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;result&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">The&nbsp;Sum&nbsp;is---</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;String.valueOf(s);&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;result;&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000">&nbsp;&nbsp;</span></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Compute的实现已经实现了，那么如何将其发布出去呢？这个是由Spring DM负责，Spring DM利用OSGi命名空间下的&lt;service&gt;元素将bean导出为OSGi服务。最简单的形式为：<br />
</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://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">&lt;</span><span style="color: #000000">beans:bean&nbsp;id</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">beanToPublish</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">com.xyz.imp.MessageServiceImp</span><span style="color: #000000">"</span><span style="color: #000000">/&gt;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #000000">&lt;</span><span style="color: #000000">service&nbsp;ref</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">beanToPublish</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">interface</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">com.xyz.MessageService</span><span style="color: #000000">"</span><span style="color: #000000">/&gt;</span><span style="color: #000000">&nbsp;</span></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 从示例中可以看出，beanToPublish被service元素声明导出。<br />
另外，service结点还有一些高级属性，如depends-on、context-class-loader、ranking等待，详情请看spring dm reference。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 首先，需要在add bundle的工程根目录下的&#8221;META-INF&#8221;的文件夹下创建一个文件夹，取名&#8221;spring&#8221;，Spring DM能够自动解析该文件夹下所有的spring配置文件。spring配置文件的具体内容如下所示：</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://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">&lt;?</span><span style="color: #000000">xml&nbsp;version</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">1.0</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;encoding</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">UTF-8</span><span style="color: #000000">"</span><span style="color: #000000">?&gt;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #000000">&lt;</span><span style="color: #000000">beans&nbsp;xmlns</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">http://www.springframework.org/schema/beans</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;xmlns:xsi</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">http://www.w3.org/2001/XMLSchema-instance</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;xmlns:osgi</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">http://www.springframework.org/schema/osgi</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;xsi:schemaLocation</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">http://www.springframework.org/schema/beans&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;http://www.springframework.org/schema/beans/spring-beans.xsd&nbsp;&nbsp;&nbsp;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;http:</span><span style="color: #008000">//</span><span style="color: #008000">www.springframework.org/schema/osgi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; text-decoration: underline">http://www.springframework.org/schema/osgi/spring-osgi.xsd</span><span style="color: #008000">"&gt;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">bean&nbsp;id</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">addOsgiService</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">osgi.example.compute.add.Add</span><span style="color: #000000">"</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;/</span><span style="color: #000000">bean</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">osgi:service&nbsp;id</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">addService</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;ref</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">addOsgiService</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">interface</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">osgi.example.compute.Compute</span><span style="color: #000000">"</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;/</span><span style="color: #000000">osgi:service</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #000000">&lt;/</span><span style="color: #000000">beans</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;</span></div>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如此一来，其他bundle就能通过spring dm引入接口类型为osgi.example.compute.Compute的服务了，spring dm将通过一定的服务查找策略，返回匹配的服务。<br />
<br />
<strong>3.&nbsp;&nbsp;&nbsp;&nbsp;bundle osgi.example.compute.multiply<br />
</strong>
<p>该bundle和add bundle相似，在这就不赘述了。<br />
<strong>4.&nbsp;&nbsp;&nbsp; bundle osgi.example.compute.client<br />
</strong></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 顾名思义，该bundle将作为add 、multiply两个bundle的客户bundle，演示如何导入服务。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OSGi的测试工作比较麻烦，这方面还没研究，在这里利用spring实例化bean的时期，从构造函数入手，对服务进行测试。Client类的实现很简单，如下所示：</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://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">package</span><span style="color: #000000">&nbsp;osgi.example.client;&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;osgi.example.compute.Compute;&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;<br />
<img id="Codehighlighter1_98_305_Open_Image" onclick="this.style.display='none'; Codehighlighter1_98_305_Open_Text.style.display='none'; Codehighlighter1_98_305_Closed_Image.style.display='inline'; Codehighlighter1_98_305_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_98_305_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_98_305_Closed_Text.style.display='none'; Codehighlighter1_98_305_Open_Image.style.display='inline'; Codehighlighter1_98_305_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Client&nbsp;</span><span id="Codehighlighter1_98_305_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://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_98_305_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;&nbsp;<br />
<img id="Codehighlighter1_107_195_Open_Image" onclick="this.style.display='none'; Codehighlighter1_107_195_Open_Text.style.display='none'; Codehighlighter1_107_195_Closed_Image.style.display='inline'; Codehighlighter1_107_195_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_107_195_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_107_195_Closed_Text.style.display='none'; Codehighlighter1_107_195_Open_Image.style.display='inline'; Codehighlighter1_107_195_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_107_195_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">/**&nbsp;*/</span><span id="Codehighlighter1_107_195_Open_Text"><span style="color: #008000">/**</span><span style="color: #008000">&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;为了方便测试，采用Spring的构造注入方式，直接在构造函数中调用Compute服务&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080">@param</span><span style="color: #008000">&nbsp;compute&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">*/</span></span><span style="color: #000000">&nbsp;&nbsp;<br />
<img id="Codehighlighter1_233_300_Open_Image" onclick="this.style.display='none'; Codehighlighter1_233_300_Open_Text.style.display='none'; Codehighlighter1_233_300_Closed_Image.style.display='inline'; Codehighlighter1_233_300_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_233_300_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_233_300_Closed_Text.style.display='none'; Codehighlighter1_233_300_Open_Image.style.display='inline'; Codehighlighter1_233_300_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;Client(Compute&nbsp;compute)</span><span id="Codehighlighter1_233_300_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://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_233_300_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(compute.computeNums(</span><span style="color: #000000">5</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">6</span><span style="color: #000000">));&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000">&nbsp;&nbsp;</span></div>
</span>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 另外，因为client用到了其他几个bundle的类型，所以需要导入相应的包，步骤在上面已有讲到。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spring dm靠&lt;reference&gt;元素来引入服务，最简单的形式如下所示：</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://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">&lt;</span><span style="color: #000000">reference&nbsp;id</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">beanToPublish</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">interface</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">com.xyz.MessageService</span><span style="color: #000000">"</span><span style="color: #000000">/&gt;</span><span style="color: #000000">&nbsp;&nbsp;</span></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果需要用到该服务，如某个bean包含一个com.xyz.MessageService属性，则配置该bean如下所示：</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://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">&lt;</span><span style="color: #000000">bean&nbsp;id</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">referenceBean</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">com.nci.ReferenceBean</span><span style="color: #000000">"</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">property&nbsp;name</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">messageService</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;ref</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">beanToPublish</span><span style="color: #000000">"</span><span style="color: #000000">/&gt;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #000000">&lt;/</span><span style="color: #000000">bean</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;</span></div>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reference元素还有一些高级属性，详情请见spring dm reference。<br />
&nbsp;&nbsp;&nbsp;&nbsp; 看一下client的spring配置文件：<br />
<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://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">&lt;?</span><span style="color: #000000">xml&nbsp;version</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">1.0</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;encoding</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">UTF-8</span><span style="color: #000000">"</span><span style="color: #000000">?&gt;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #000000">&lt;</span><span style="color: #000000">beans&nbsp;xmlns</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">http://www.springframework.org/schema/beans</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;xmlns:xsi</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">http://www.w3.org/2001/XMLSchema-instance</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;xmlns:osgi</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">http://www.springframework.org/schema/osgi</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;xsi:schemaLocation</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">http://www.springframework.org/schema/beans&nbsp;http://www.springframework.org/schema/beans/spring-beans.xsd&nbsp;&nbsp;&nbsp;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;http:</span><span style="color: #008000">//</span><span style="color: #008000">www.springframework.org/schema/osgi&nbsp;</span><span style="color: #008000; text-decoration: underline">http://www.springframework.org/schema/osgi/spring-osgi.xsd</span><span style="color: #008000">"&gt;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">bean&nbsp;id</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">OSGiClient</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">osgi.example.client.Client</span><span style="color: #000000">"</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">constructor</span><span style="color: #000000">-</span><span style="color: #000000">arg&nbsp;ref</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">ComputeService</span><span style="color: #000000">"</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;/</span><span style="color: #000000">constructor</span><span style="color: #000000">-</span><span style="color: #000000">arg</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;/</span><span style="color: #000000">bean</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">osgi:reference&nbsp;id</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">ComputeService</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">interface</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">osgi.example.compute.Compute</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;cardinality</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">1..1</span><span style="color: #000000">"</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;/</span><span style="color: #000000">osgi:reference</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #000000">&lt;/</span><span style="color: #000000">beans</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;</span></div>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 从上面的示例，我们可以发现，服务的导出的时候都是基于接口的，服务的引用也是基于接口的，不过spring dm支持基于类的导出、导入，但是还是建议尽量基于接口，应该记住面向接口编程的思想，以应对将来有可能发生的改变。<br />
<br />
<strong>5.&nbsp;&nbsp; &nbsp;运行<br />
</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;由于add和multiply都是基于Compute接口对外导出服务，那么Client到底导入的是哪个服务呢？默认情况下，会导入启动较早的bundle服务（OSGi在bundle启动时，会为其分配一个ID值，启动越早，该值越小）。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 运行之前，我们需要做这么一件事，在window-&gt;preferences-&gt;plug-in development-&gt;Target Platform面板中，将Target指定为Spring DM&#8230;，如下图所示：<br />
<img height="597" alt="" src="http://www.blogjava.net/images/blogjava_net/benniaolk/OSGi/Spring与OSGi的整合/12.png" width="1007" border="0" /><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 之后就可以配置运行了，随便在一个bundle工程上右键，Run As-&gt;Run Configurations，新建一个OSGi Platform运行项（右键OSGi Platform即可），如下图所示：<br />
<img height="652" alt="" src="http://www.blogjava.net/images/blogjava_net/benniaolk/OSGi/Spring与OSGi的整合/13.png" width="958" border="0" /><br />
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;需要勾选中spring bundle版（2.5.6），spring dm的几个核心包：core、extender、io再点validate bundles按钮，校验是否已全部选中其依赖的bundle。然后即可点击运行了。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 运行之后，我们发现控制台输出结果：<br />
The Sum is---11<br />
通过ss命令，如下：<br />
5&nbsp;ACTIVE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; osgi.example.compute.multiply_1.0.0<br />
6&nbsp;ACTIVE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; osgi.example.compute.add_1.0.0<br />
7&nbsp;ACTIVE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; osgi.example.compute.client_1.0.0<br />
将6停掉:stop 6<br />
然后再refresh 7，控制台输出如下结果：<br />
The Multiply is---30<br />
通过 ss 命令，如下：<br />
5&nbsp;ACTIVE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; osgi.example.compute.multiply_1.0.0<br />
6&nbsp;RESOLVED&nbsp;&nbsp;&nbsp; osgi.example.compute.add_1.0.0<br />
7&nbsp;ACTIVE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; osgi.example.compute.client_1.0.0<br />
现在multiply处于运行状态，而add已经被停止，所以client导入的服务实际是由multiply提供的。<br />
</p>
<p><strong>6.&nbsp;总结</strong>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 通过该文档，我们已经清楚了，如何使用Spring DM导出、导入服务。Spring DM的一些高级特性请查阅spring dm reference。<br />
<br />
<br />
<strong><em>附件：<a href="/Files/benniaolk/OSGi/Spring与OSGi的整合/1.rar">osgi.example.compute.rar</a></em></strong><br />
</p>
  <img src ="http://www.blogjava.net/benniaolk/aggbug/316756.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/benniaolk/" target="_blank">Dreava</a> 2010-03-28 17:36 <a href="http://www.blogjava.net/benniaolk/articles/316756.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于Equinox开发HelloWorld</title><link>http://www.blogjava.net/benniaolk/articles/316755.html</link><dc:creator>Dreava</dc:creator><author>Dreava</author><pubDate>Sun, 28 Mar 2010 08:58:00 GMT</pubDate><guid>http://www.blogjava.net/benniaolk/articles/316755.html</guid><wfw:comment>http://www.blogjava.net/benniaolk/comments/316755.html</wfw:comment><comments>http://www.blogjava.net/benniaolk/articles/316755.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/benniaolk/comments/commentRss/316755.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/benniaolk/services/trackbacks/316755.html</trackback:ping><description><![CDATA[<p>1.&nbsp;开发环境的准备</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 现在的eclipse都已经包含了Equinox，无需单独下载。<br />
2.&nbsp;开发OSGi的HelloWorld应用程序</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在这一节，我们将开发一个OSGi bundle，演示如何利用Equinox进行OSGi bundle的开发、运行及调试，为之后的示例做准备。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 首先，新建一个Plug-in工程，如下图所示：<br />
<img height="598" alt="" src="http://www.blogjava.net/images/blogjava_net/benniaolk/OSGi/Spring与OSGi的整合/1.jpg" width="506" border="0" /><br />
</p>
<p><span>下一步，注意选择目标平台，默认为Eclipse version *，将其改成Equinox，如下图所示：</span></p>
<img height="594" alt="" src="http://www.blogjava.net/images/blogjava_net/benniaolk/OSGi/Spring与OSGi的整合/2.png" width="499" border="0" /><br />
<p><span>之后按默认下一步即可，到最后一步时，无需根据模板创建工程，去掉默认的勾，如下图：</span></p>
<img height="593" alt="" src="http://www.blogjava.net/images/blogjava_net/benniaolk/OSGi/Spring与OSGi的整合/3.png" width="501" border="0" /><br />
<p><span>点击完成，创建的工程目录如下图所示：</span></p>
<img height="428" alt="" src="http://www.blogjava.net/images/blogjava_net/benniaolk/OSGi/Spring与OSGi的整合/4.png" width="682" border="0" /><br />
<span style="font-family: Calibri">从图中，可以看到，eclipse为工程自动生成了一个Activator类，如下所示：</span><br />
<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 alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="color: #0000ff">package</span><span style="color: #000000">&nbsp;helloworld;&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;org.osgi.framework.BundleActivator;&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;org.osgi.framework.BundleContext;&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;<br />
<img id="Codehighlighter1_169_642_Open_Image" onclick="this.style.display='none'; Codehighlighter1_169_642_Open_Text.style.display='none'; Codehighlighter1_169_642_Closed_Image.style.display='inline'; Codehighlighter1_169_642_Closed_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_169_642_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_169_642_Closed_Text.style.display='none'; Codehighlighter1_169_642_Open_Image.style.display='inline'; Codehighlighter1_169_642_Open_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Activator&nbsp;</span><span style="color: #0000ff">implements</span><span style="color: #000000">&nbsp;BundleActivator&nbsp;</span><span id="Codehighlighter1_169_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 alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_169_642_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;<br />
<img id="Codehighlighter1_181_304_Open_Image" onclick="this.style.display='none'; Codehighlighter1_181_304_Open_Text.style.display='none'; Codehighlighter1_181_304_Closed_Image.style.display='inline'; Codehighlighter1_181_304_Closed_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_181_304_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_181_304_Closed_Text.style.display='none'; Codehighlighter1_181_304_Open_Image.style.display='inline'; Codehighlighter1_181_304_Open_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_181_304_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_181_304_Open_Text"><span style="color: #008000">/*</span><span style="color: #008000">&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;(non-Javadoc)&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">*/</span></span><span style="color: #000000">&nbsp;&nbsp;<br />
<img id="Codehighlighter1_370_426_Open_Image" onclick="this.style.display='none'; Codehighlighter1_370_426_Open_Text.style.display='none'; Codehighlighter1_370_426_Closed_Image.style.display='inline'; Codehighlighter1_370_426_Closed_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_370_426_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_370_426_Closed_Text.style.display='none'; Codehighlighter1_370_426_Open_Image.style.display='inline'; Codehighlighter1_370_426_Open_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;start(BundleContext&nbsp;context)&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;Exception&nbsp;</span><span id="Codehighlighter1_370_426_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 alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_370_426_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">Hello&nbsp;World!</span><span style="color: #000000">"</span><span style="color: #000000">);&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;<br />
<img id="Codehighlighter1_438_560_Open_Image" onclick="this.style.display='none'; Codehighlighter1_438_560_Open_Text.style.display='none'; Codehighlighter1_438_560_Closed_Image.style.display='inline'; Codehighlighter1_438_560_Closed_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_438_560_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_438_560_Closed_Text.style.display='none'; Codehighlighter1_438_560_Open_Image.style.display='inline'; Codehighlighter1_438_560_Open_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_438_560_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_438_560_Open_Text"><span style="color: #008000">/*</span><span style="color: #008000">&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;(non-Javadoc)&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">*/</span></span><span style="color: #000000">&nbsp;&nbsp;<br />
<img id="Codehighlighter1_625_634_Open_Image" onclick="this.style.display='none'; Codehighlighter1_625_634_Open_Text.style.display='none'; Codehighlighter1_625_634_Closed_Image.style.display='inline'; Codehighlighter1_625_634_Closed_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_625_634_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_625_634_Closed_Text.style.display='none'; Codehighlighter1_625_634_Open_Image.style.display='inline'; Codehighlighter1_625_634_Open_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;stop(BundleContext&nbsp;context)&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;Exception&nbsp;</span><span id="Codehighlighter1_625_634_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 alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_625_634_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: #000000">&nbsp;&nbsp;</span></div>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 有过eclipse插件开发经验的人应该很快就能明白，这就是该工程——实际上就是上一篇文章中所称的bundle在Equinox平台中的启动入口，相当于我们的熟悉的main函数，如果将该bundle运行到Equinox中，首先进入该bundle的是Activator的start方法，你可以将相关的服务、资源在该方法内完成向bundleContext的注册——文章后面会具体讲到相关内容。在运行期，如果想要该bundle停止运行，Equinox平台将调用Activator的stop方法，你可以在该方法内完成资源的注销等工作。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 下面我们将要完成首次的Equinox运行，将向大家展现bundle到底是如何运行起来的。为helloworld选择运行方式，如下图所示：<br />
<img height="129" alt="" src="http://www.blogjava.net/images/blogjava_net/benniaolk/OSGi/Spring与OSGi的整合/5.png" width="528" border="0" /><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 弹出如下对话框：<br />
<img height="129" alt="" src="http://www.blogjava.net/images/blogjava_net/benniaolk/OSGi/Spring与OSGi的整合/5.png" width="528" border="0" /><br />
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在弹出的对话框中，新建一个OSGi Framework运行环境（双击OSGi Framework即可，这里为其取名Equinox），选中helloworld(1.0.0)，然后点击右边的Add Required Bundles按钮，eclipse将自动选中运行helloworld的依赖bundle，如果有必要，可以点击右下的Validate Bundles验证按钮，验证程序正常运行所需的bundle是否都被选中，最后点击运行，回到控制台：<br />
osgi&gt; Hello World!<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 可以看到，之前在Activator的start方法中的输出语句已经被输出到控制台，我们可以通过命令ss查看Equinox的运行情况，可以看到一共运行了两个bundle，如下：<br />
ss</p>
<p>Framework is launched.</p>
<p>id&nbsp;State&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Bundle<br />
0&nbsp;ACTIVE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.eclipse.osgi_3.4.3.R34x_v20081215-1030<br />
1&nbsp;ACTIVE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; helloworld_1.0.0<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 还记得之前讲到过的bundle的几种状态吧？helloworld已经运行起来了。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 那么Equinox具体支持哪些命令呢？下表列出了主要的一些命令，如需查看更详细的命令清单，则可以在控制台键入help。</p>
<table style="border-right: medium none; border-top: medium none; border-left: medium none; border-bottom: medium none; border-collapse: collapse" cellspacing="0" cellpadding="0" border="1">
    <tbody>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; border-top: #8064a2 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: #8064a2 1pt solid; width: 142pt; padding-top: 0cm; border-bottom: #8064a2 2.25pt solid; background-color: transparent" valign="top" width="189">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><strong>类别</strong></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; border-top: #8064a2 1pt solid; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 68.95pt; padding-top: 0cm; border-bottom: #8064a2 2.25pt solid; background-color: transparent" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><strong>命令</strong></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; border-top: #8064a2 1pt solid; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 215.15pt; padding-top: 0cm; border-bottom: #8064a2 2.25pt solid; background-color: transparent" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><strong>含义</strong></p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; background: #e5dfec; padding-bottom: 0cm; border-left: #8064a2 1pt solid; width: 142pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" width="189" rowspan="6">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><strong>控制框架</strong></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">launch</code></span></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">启动框架</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">shutdown</code></span></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">停止框架</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">close</code></span></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">关闭、退出框架</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">exit</code></span></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">立即退出，相当于 System.exit</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">init</code></span></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">卸载所有 bundle（前提是已经 shutdown）</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">setprop</code></span></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">设置属性，在运行时进行</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; background: #e5dfec; padding-bottom: 0cm; border-left: #8064a2 1pt solid; width: 142pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" width="189" rowspan="6">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><strong>控制</strong><strong> bundle</strong></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">install</code></span></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">安装</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">uninstall</code></span></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">卸载</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">start</code></span></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">启动</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">stop</code></span></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">停止</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">refresh</code></span></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">刷新</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">update</code></span></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">更新</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; background: #e5dfec; padding-bottom: 0cm; border-left: #8064a2 1pt solid; width: 142pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" width="189" rowspan="7">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><strong>展示状态</strong></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">status</code></span></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">展示安装的 bundle 和注册的服务</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">ss</code></span></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">展示所有 bundle 的简单状态</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><span style="font-size: small"><span style="font-family: Calibri">s</span><code><span style="font-size: 12pt; color: #000000">ervices</span></code></span></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">展示注册服务的详细信息</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">packages</code></span></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">展示导入、导出包的状态</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">bundles</code></span></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">展示所有已经安装的 bundles 的状态</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">headers</span></code></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">展示 bundles 的头信息，即 MANIFEST.MF 中的内容</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">log</span></code></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">展示 LOG 入口信息</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; background: #e5dfec; padding-bottom: 0cm; border-left: #8064a2 1pt solid; width: 142pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" width="189" rowspan="4">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><strong>其它</strong></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">exec</span></code></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">在另外一个进程中执行一个命令（阻塞状态）</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">fork</span></code></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">和 EXEC 不同的是不会引起阻塞</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">gc</span></code></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">促使垃圾回收</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">getprop</span></code></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">得到属性，或者某个属性</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; background: #e5dfec; padding-bottom: 0cm; border-left: #8064a2 1pt solid; width: 142pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" width="189" rowspan="4">
            <p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><strong>控制启动级别</strong></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">sl</span></code></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">得到某个 bundle 或者整个框架的 start level 信息</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">setfwsl</span></code></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">设置框架的 start level</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">setbsl</span></code></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid; background-color: transparent" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">设置 bundle 的 start level</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 68.95pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="92">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left"><code><span style="font-size: 12pt; color: #000000">setibsl</span></code></p>
            </td>
            <td style="border-right: #8064a2 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #ece9d8; background: #dfd8e8; padding-bottom: 0cm; width: 215.15pt; border-top-color: #ece9d8; padding-top: 0cm; border-bottom: #8064a2 1pt solid" valign="top" width="287">
            <p style="margin: 0cm 0cm 0pt; text-align: left" align="left">设置初始化 bundle 的 start level</p>
            </td>
        </tr>
    </tbody>
</table>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 至此，我们已经成功的演示了helloworld，初步了解了OSGi的bundle是如何开发并运行的。<br />
<br />
</p>
<img src ="http://www.blogjava.net/benniaolk/aggbug/316755.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/benniaolk/" target="_blank">Dreava</a> 2010-03-28 16:58 <a href="http://www.blogjava.net/benniaolk/articles/316755.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GEF实现Eclipse的Outline视图</title><link>http://www.blogjava.net/benniaolk/articles/316754.html</link><dc:creator>Dreava</dc:creator><author>Dreava</author><pubDate>Sun, 28 Mar 2010 08:39:00 GMT</pubDate><guid>http://www.blogjava.net/benniaolk/articles/316754.html</guid><wfw:comment>http://www.blogjava.net/benniaolk/comments/316754.html</wfw:comment><comments>http://www.blogjava.net/benniaolk/articles/316754.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/benniaolk/comments/commentRss/316754.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/benniaolk/services/trackbacks/316754.html</trackback:ping><description><![CDATA[<p>1、&nbsp;首先要实现EditPartFactory接口——EditPartFactoryOutlineImp，该接口为Outline视图提供控制器EditPart对象，注意该EditPartFactoryImp要与编辑视图——即真正的编辑区的EditPartFactory接口实现类PartFactoryEditAreaImp保持一致，否则无法同步编辑区与Outline的同步。当然，并不是编辑区的所有元素都应反应到Outline视图中，这要根据自己的需要在EditPartFactoryOutlineImp创建EditPart对象。<br />
2、&nbsp;Outline视图中的树控制器的构建：需要实现EditPartFactory接口——TreePartFactory，实现public EditPart createEditPart(EditPart context, Object model)方法，在该方法里为每个结点——model创建其子模型的树模型。Outline的树结构的根结点应该在编辑区的——GraphicalEditorWithFlyoutPalette继承类的内部类ContentOutlinePage继承类的public void createControl(Composite parent)方法中进行创建，通过getViewer().setContents(model)方法将根模型注入Outline视图中。<br />
另外，为了维护Outline的树，需要继承AbstractTreeEditPart，及实现PropertyChangeListener接口，主要需要重载或实现的一些方法为：</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://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #008000">//</span><span style="color: #008000">此方法负责处理由于鼠标选中或更改对树造成的变化，对树结构进行刷新&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;propertyChange(PropertyChangeEvent&nbsp;evt)&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #008000">//</span><span style="color: #008000">树结点的图标&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">protected</span><span style="color: #000000">&nbsp;Image&nbsp;getImage()&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #008000">//</span><span style="color: #008000">树结点的文本&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">protected</span><span style="color: #000000">&nbsp;String&nbsp;getText()&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #008000">//</span><span style="color: #008000">该方法负责处理由于鼠标选中或其他事件激活某树结点该做的事情，如果为该树结点添加PropertyChangeListener。&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;activate()&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #008000">//</span><span style="color: #008000">与上面的方法相反&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;deactivate()&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #008000">//</span><span style="color: #008000">得到当前树结点的模型&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">protected</span><span style="color: #000000">&nbsp;List&nbsp;getModelChildren()&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span></div>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 补充资料：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在Eclipse 里，当编辑器（Editor）被激活时，大纲视图自动通过这个编辑器的getAdapter()方法寻找它提供的大纲（大纲实现IcontentOutlinePage 接口）。GEF 提供了ContentOutlinePage 类用来实现大纲视图，我们要做的就是实现一个它的子类，并重点实现createControl()方法。ContentOutlinePage 是org.eclipse.ui.part.Page 的一个子类，大纲视图则是PageBookView 的子类，在大纲视图中有一个PageBook，包含了很多Page 并可以在它们之间切换，切换的依据就是当前活动的Editor。因此，我们在createControl()方法里要做的就是构造这个Page，简化后的代码如下所示：</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://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;Control&nbsp;outline;&nbsp;&nbsp;&nbsp;<br />
<img id="Codehighlighter1_49_85_Open_Image" onclick="this.style.display='none'; Codehighlighter1_49_85_Open_Text.style.display='none'; Codehighlighter1_49_85_Closed_Image.style.display='inline'; Codehighlighter1_49_85_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_49_85_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_49_85_Closed_Text.style.display='none'; Codehighlighter1_49_85_Open_Image.style.display='inline'; Codehighlighter1_49_85_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;OutlinePage()&nbsp;</span><span id="Codehighlighter1_49_85_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://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_49_85_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">super</span><span style="color: #000000">(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;TreeViewer());&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<br />
<img id="Codehighlighter1_134_408_Open_Image" onclick="this.style.display='none'; Codehighlighter1_134_408_Open_Text.style.display='none'; Codehighlighter1_134_408_Closed_Image.style.display='inline'; Codehighlighter1_134_408_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_134_408_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_134_408_Closed_Text.style.display='none'; Codehighlighter1_134_408_Open_Image.style.display='inline'; Codehighlighter1_134_408_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;createControl(Composite&nbsp;parent)&nbsp;</span><span id="Codehighlighter1_134_408_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://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_134_408_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;outline&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;getViewer().createControl(parent);&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;getSelectionSynchronizer().addViewer(getViewer());&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;getViewer().setEditDomain(getEditDomain());&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;getViewer().setEditPartFactory(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;TreePartFactory());&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;getViewer().setContents(getDiagram());&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000">&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 由于我们在构造方法里指定了使用树结构显示大纲，所以createControl()里的第一句就会使outline 变量得到一个Tree（见org.eclipse.gef.ui.parts.TreeViewer 的代码），第二句把TreeViewer 加到选择同步器中，从而让用户不论在大纲或编辑区域里选择EditPart 时，另一方都能自动做出同样的选择；最后三行的作用在以前的帖子里都有介绍，总体目的是把大纲视图的模型与编辑区域的模型联系在一起，这样，对于同一个模型我们就有了两个视图，体会到MVC 的好处了吧。<br />
实现大纲视图最重要的工作基本就是这些，但还没有完，我们要在init()方法里绑定UNDO/REDO/DELETE 等命令到Eclipse 主窗口，否则当大纲视图处于活动状态时，主工具条上的这些命令就会变为不可用状态；在 getControl()方法里要返回我们的outline 成员变量，也就是指定让这个控件出现在大纲视图中；在dispose()方法里应该把这个TreeViewer 从选择同步器中移除；最后，必须在PracticeEditor 里覆盖getAdapter()方法，前面说过，这个方法是在Editor 激活时被大纲视图调用的，所以在这里必须把我们实现好的OutlinePage 返回给大纲视图使用，代码如下：</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 id="Codehighlighter1_37_153_Open_Image" onclick="this.style.display='none'; Codehighlighter1_37_153_Open_Text.style.display='none'; Codehighlighter1_37_153_Closed_Image.style.display='inline'; Codehighlighter1_37_153_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_37_153_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_37_153_Closed_Text.style.display='none'; Codehighlighter1_37_153_Open_Image.style.display='inline'; Codehighlighter1_37_153_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;Object&nbsp;getAdapter(Class&nbsp;type)&nbsp;</span><span id="Codehighlighter1_37_153_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://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_37_153_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(type&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;IContentOutlinePage.</span><span style="color: #0000ff">class</span><span style="color: #000000">)&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;OutlinePage();&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">super</span><span style="color: #000000">.getAdapter(type);&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000">&nbsp;&nbsp;<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span></div>
<img src ="http://www.blogjava.net/benniaolk/aggbug/316754.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/benniaolk/" target="_blank">Dreava</a> 2010-03-28 16:39 <a href="http://www.blogjava.net/benniaolk/articles/316754.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java序列化及反序列化</title><link>http://www.blogjava.net/benniaolk/articles/316753.html</link><dc:creator>Dreava</dc:creator><author>Dreava</author><pubDate>Sun, 28 Mar 2010 08:33:00 GMT</pubDate><guid>http://www.blogjava.net/benniaolk/articles/316753.html</guid><wfw:comment>http://www.blogjava.net/benniaolk/comments/316753.html</wfw:comment><comments>http://www.blogjava.net/benniaolk/articles/316753.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/benniaolk/comments/commentRss/316753.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/benniaolk/services/trackbacks/316753.html</trackback:ping><description><![CDATA[<h1><span style="font-size: medium">1.概述</span></h1>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 要实现序列化，则必须实现serializable或Externalizable接口。后者继承自前者，两者的区别：实现前者的类可以采用默认的序列化方式。而实现后者的类则完全由自身来控制序列化的行为。<br />
&nbsp;&nbsp;&nbsp;&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"><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;writeObject&nbsp;java.io.ObjectOutputStream&nbsp;out)&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;IOException&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;readObject(java.io.ObjectInputStream&nbsp;in)&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;IOException,&nbsp;ClassNotFoundException;&nbsp;&nbsp;</span></div>
<br />
&nbsp;&nbsp;&nbsp;&nbsp; writeObject 方法负责写入特定类的对象的状态，以便相应的 readObject 方法可以还原它。通过调用 out.defaultWriteObject 可以调用保存 Object 的字段的默认机制。该方法本身不需要涉及属于其超类或子类的状态。状态是通过使用 writeObject 方法或使用 DataOutput 支持的用于基本数据类型的方法将各个字段写入 ObjectOutputStream 来保存的。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; readObject 方法负责从流中读取并还原类字段。它可以调用 in.defaultReadObject 来调用默认机制，以还原对象的非静态和非瞬态字段。defaultReadObject 方法使用流中的信息来分配流中通过当前对象中相应命名字段保存的对象的字段。这用于处理类发展后需要添加新字段的情形。该方法本身不需要涉及属于其超类或子类的状态。状态是通过使用 writeObject 方法或使用 DataOutput 支持的用于基本数据类型的方法将各个字段写入 ObjectOutputStream 来保存的。&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;假定有一个名为Customer的类，它的对象需要序列化，如果Customer类仅仅实现了Serializable接口的类，那么将按照以下方式序列化及反序列化Customer对象：<br />
<ul>
    <li>ObjectOutputStream采用默认的序列化方式，对Customer对象的非transient的实例变量进行序列化。
    <li>ObjectInputStream采用默认的反序列化方式，对Customer对象的非transient的实例变量进行反序列化。 </li>
</ul>
&nbsp;&nbsp; 如果Customer类仅仅实现了Serializable接口的类，并且还定义了readObject(ObjectInputStream in)和writeObject(ObjectOutputStream out)方法，那么将按照以下方式序列化及反序化Customer对象：
<ul>
    <li>ObjectOutputStream会调用Customer类的writeObject(ObjectOutputStream out)方法来进行序列化。
    <li>ObjectInputStream会调用Customer类的readObject(ObjectInputStream in)方法来进行反序列化。 </li>
</ul>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 如果Customer类实现了Externalizable接口，那么Customer类必须实现readExternal<br />
&nbsp;&nbsp;&nbsp;&nbsp; (ObjectInput in)和writeExternal(ObjectOutput out)方法。在这种情况下，将按照以下方式序列化及反序列化Customer对象：</p>
<ul>
    <li>ObjectOutputStream会调用Customer类的writeExternal(ObjectOutput out)方法来进行序列化。
    <li>&nbsp;ObjectInputStream先通过Customer类的不带参数的构造方法创建一个Customer对象，然后调用它的readExternal(ObjectInput int)方法来进行反序列化。 </li>
</ul>
<h1><span style="font-size: medium">2.实现Serializable接口</span></h1>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ObjectOutputStream只能对实现了Serializable接口的类的对象进行序列化。默认情况下，ObjectOutputStream按照默认方式序列化，这种序列化方式仅仅对对象的非transient的实例变量进行序列化，而不会序列化对象的transient的实例变量，也不会序列化静态变量。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 而当ObjectInputStream按照默认方式反序列化时，有以下特点：</p>
<ul>
    <li>如果在内在中对象所属的类还没有被加载，那么会先加载并初始化这个类。如果在classpath中不存在相应的类文件，那么会抛出ClassNotFoundException。
    <li>在反序列化时不会调用类的任何构造方法。 </li>
</ul>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 被transient修饰符来修饰的实例变量是不会序列化的，一般用transient来修饰以下类型的的变量：</p>
<p>&nbsp;&nbsp;&nbsp; １）&nbsp;实例变量不代表对象的固有的内部数据，仅仅代表具有一定逻辑含义的临时数据。<br />
&nbsp;&nbsp;&nbsp; ２）&nbsp;实例变量表示一些比较敏感的信息，如密码，出于安全方面的原因，不希望对其序列化。<br />
&nbsp;&nbsp;&nbsp; ３）&nbsp;实例变量需要按照用户自定义的方式序列化，如经过加密后再序列化。这这种情况下可以将其用transient修饰，然后在writeObject()方法中对其序列化。&nbsp;&nbsp;&nbsp; </p>
<h2>２.１序列化对象图</h2>
<p>&nbsp;&nbsp;&nbsp; 参见SerializableDemo中的Customer2及Order2类之间的关系。<br />
&nbsp;&nbsp;&nbsp; 当通过ObjectOutputStream对象的writeObject(customer)方法序列化Customer2对象时，也会序列化与它关联的Order2对象。而当通过ObjectInputStream对象的readObject()方法反序列化Customer2对象时，实际上会对整个对象图反序列化。<br />
&nbsp;&nbsp;&nbsp; 如果对象A持有对象B的引用（注意是A持有B的引用），以及间接持有其他对象的引用，则按照默认方式序列化对象A时，会将A以及A持有的以及间接持有的所有对象都序列化。反序列化也是如此。</p>
<p>&nbsp;&nbsp;&nbsp; </p>
<h2>２.２控制序列化的行为</h2>
<p>&nbsp;&nbsp;&nbsp;&nbsp;如果用户希望控制类的序列化方式，可以在可序列化类中提供以下形式的writeObject()方法和readObject()方法：</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://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;writeObject&nbsp;java.io.ObjectOutputStream&nbsp;out)</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;IOException&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;readObject&nbsp;java.io.ObjectInputStream&nbsp;in)</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;IOException,ClassNotFoundException;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;一般的做法是，在writeObject()方法中，选留骼ObjectOutputStream的defaultWriteObject()方法，使得对象输出流先执行默认的序列化操作。<br />
&nbsp;&nbsp;&nbsp; 反序列化时，在readObject()方法中，先调用ObjectInputStream的defaultReadObject()方法。</p>
<p>&nbsp;&nbsp;&nbsp; </p>
<h2>２.３readResolve()方法在童便类中的运用</h2>
<p><br />
&nbsp;&nbsp;&nbsp; 如果一个类提供了readResolve()方法，那么在执行反序列化操作时，先按照默认方式或者用户自定义的方式进行反序列化，最后再调用readResolve()方法，该方法返回的对象为反序列化的最终结果。<br />
&nbsp;&nbsp;&nbsp; readResolve()方法应该能够被类本身、同一个包中的类，或者访问，因此readResolve()方法的访问权限可以是pirvate、默认或protected级别。<br />
&nbsp;&nbsp;&nbsp; readResolve()方法用来重新指定反序列化得到的对象，与此对应，Java序列化规范还允许在可序列化类中定义一个writeReplace()方法，用来重新指定被序列化的对象。writeReplace()方法返回一个Object类型的对象，这个返回对象才是真正要被序列化的对象。权限也可以为以上三种之一。&nbsp;&nbsp; </p>
<h1>３.实现Externalizalbe接口</h1>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Externallizable接口继承自Serializable接口，如果一个类实现了Externalizable接口，那么将完全由这个类控制自身的序列化行为。Externalizable接口中声明了两个方法：<br />
</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://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;writeExternal(ObjectOutput&nbsp;out)</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;IOException&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;readExternal(ObjectInput&nbsp;in)&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;IOException,ClassNotFoundException&nbsp;&nbsp;</span></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;writeExternal负责序列化操作，readExternal负责反序列化操作。在对实现了Externallizable接口的类的对象进行反序列化时，会先调用类的不带参数的构造方法，这是有别默认反序列化方式的（见２）。所以实现Externalizable接口的类必须要有不含参数的构造方法。</p>
<p>&nbsp;</p>
<h1>４.可序列化类的不同版本的序列化兼容性</h1>
<p>&nbsp;&nbsp;&nbsp; 实例见SerializableDemo里的Customer5的两个版本。将Customer１.０和SimpleServer放在server端，将Customer2.0和SimpleClient放在Client端，直接运行，将发现抛出错误，显示不兼容，解决办法是手动将两个Customer的serialVersionUID设为同一个值，这样就能兼容。但是这种办法的能力很有限，当一个类的不同版本的serialVersionUID相同，仍然有可能出现序列化不兼容的情况。因为序列化兼容性不仅取决于serialVersionUID，还取决于类的不同版本的实现细节和序列化细节。</p>
<img src ="http://www.blogjava.net/benniaolk/aggbug/316753.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/benniaolk/" target="_blank">Dreava</a> 2010-03-28 16:33 <a href="http://www.blogjava.net/benniaolk/articles/316753.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>详解finalize()</title><link>http://www.blogjava.net/benniaolk/articles/316752.html</link><dc:creator>Dreava</dc:creator><author>Dreava</author><pubDate>Sun, 28 Mar 2010 08:18:00 GMT</pubDate><guid>http://www.blogjava.net/benniaolk/articles/316752.html</guid><wfw:comment>http://www.blogjava.net/benniaolk/comments/316752.html</wfw:comment><comments>http://www.blogjava.net/benniaolk/articles/316752.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/benniaolk/comments/commentRss/316752.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/benniaolk/services/trackbacks/316752.html</trackback:ping><description><![CDATA[&nbsp;
<p style="text-indent: 21pt"><span style="font-family: 宋体">网上很多关于面试笔试的一些题目，基本上都问到了同一个问题，</span>finalize()<span style="font-family: 宋体">的作用是什么？网上给的答案说的可能比较笼统，今天又重温了一遍</span>Thinking in Java<span style="font-family: 宋体">，又回顾了一下</span>finalize()<span style="font-family: 宋体">的意义和作用，特意写出来，姑且作为备忘之用。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">估计大家对</span>finalize()<span style="font-family: 宋体">都有个基本的认识，那就是作清理资源之用。比如在类的某个方法中打开了一个文件，那么你可能需要通过</span>finalize()<span style="font-family: 宋体">方法来释放该资源。但是话说回来，</span>java<span style="font-family: 宋体">世界里，一切皆对象，而任何一个学</span>java<span style="font-family: 宋体">的人都知道，</span>java<span style="font-family: 宋体">对象是不需要手动去清理的，因为</span>java<span style="font-family: 宋体">有强大的垃圾回收器，有人可能会有疑问，那既然如此，为什么还需要在</span>finalize()<span style="font-family: 宋体">中手动释放资源呢？当然，面对这一问题，有很好的理由去解释，因为资源是有限的，而我们又知道垃圾回收器的线程优先级非常低，在逼不得以的情况下，它才会工作，也就是说，只要内存足够，失效的对象就不会被清理，它所持有的资源也就得不到释放，而资源又是有限的，比如数据库连接，所以需要我们去手动释放。不过这一点，在</span>JDK7<span style="font-family: 宋体">里面似乎是有所发展，听说是会自动实现这一点，也就是说，</span>sun<span style="font-family: 宋体">可能为我们做了这个工作，以后的程序中可能不需要手动释放类似数据库资源的代码了。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">如果的确如此，那是不是意味着</span>finalize()<span style="font-family: 宋体">就没用了呢？错。不过</span>finalize()<span style="font-family: 宋体">确实用到的时候不会很多，它主要用于一些本地方法调用过程中产生的资源清理。比如你通过</span>Native method<span style="font-family: 宋体">调用</span>c<span style="font-family: 宋体">语言的</span>melloc<span style="font-family: 宋体">方法分配了一些内存空间，而这部分内存是需要</span>c<span style="font-family: 宋体">语言的</span>free()<span style="font-family: 宋体">来进行释放的，如果不这样，就会产生内存泄漏，所以你需要在</span>finalize()<span style="font-family: 宋体">中用</span>Native method<span style="font-family: 宋体">方法调用</span>free()<span style="font-family: 宋体">将其释放。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">不过话说回来，</span>finalize()<span style="font-family: 宋体">方法并不十分保险，因为</span>finalize()<span style="font-family: 宋体">只有在垃圾回收器工作的时候才会被调用，也就是说，通过它进行资源释放并不能确保马上被释放，甚至可能根本不会被释放（因为垃圾回收器可能不会工作），因此，资源释放尽量另想办法，别太相信</span>finalize()<span style="font-family: 宋体">和垃圾回收器了。</span></p>
 <img src ="http://www.blogjava.net/benniaolk/aggbug/316752.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/benniaolk/" target="_blank">Dreava</a> 2010-03-28 16:18 <a href="http://www.blogjava.net/benniaolk/articles/316752.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>乔迁声明</title><link>http://www.blogjava.net/benniaolk/archive/2010/03/28/316751.html</link><dc:creator>Dreava</dc:creator><author>Dreava</author><pubDate>Sun, 28 Mar 2010 08:11:00 GMT</pubDate><guid>http://www.blogjava.net/benniaolk/archive/2010/03/28/316751.html</guid><wfw:comment>http://www.blogjava.net/benniaolk/comments/316751.html</wfw:comment><comments>http://www.blogjava.net/benniaolk/archive/2010/03/28/316751.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/benniaolk/comments/commentRss/316751.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/benniaolk/services/trackbacks/316751.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 从JavaEye迁至于此&nbsp;&nbsp;<a href='http://www.blogjava.net/benniaolk/archive/2010/03/28/316751.html'>阅读全文</a><img src ="http://www.blogjava.net/benniaolk/aggbug/316751.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/benniaolk/" target="_blank">Dreava</a> 2010-03-28 16:11 <a href="http://www.blogjava.net/benniaolk/archive/2010/03/28/316751.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OSGi和构件化开发</title><link>http://www.blogjava.net/benniaolk/articles/316738.html</link><dc:creator>Dreava</dc:creator><author>Dreava</author><pubDate>Sun, 28 Mar 2010 03:49:00 GMT</pubDate><guid>http://www.blogjava.net/benniaolk/articles/316738.html</guid><wfw:comment>http://www.blogjava.net/benniaolk/comments/316738.html</wfw:comment><comments>http://www.blogjava.net/benniaolk/articles/316738.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/benniaolk/comments/commentRss/316738.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/benniaolk/services/trackbacks/316738.html</trackback:ping><description><![CDATA[<p>&nbsp; </p>
<p style="text-indent: 24pt"><span style="font-family: 宋体">目前，关注</span>OSGi<span style="font-family: 宋体">的人变得越来越多，</span>OSGi<span style="font-family: 宋体">本身也早已从那个专注于嵌入式平台的&#8220;小&#8221;角色转变过来了，慢慢向企业级应用市场渗透。</span></p>
<p style="text-indent: 24pt"><span style="font-family: 宋体">从某种角度说，</span>Eclipse<span style="font-family: 宋体">可以说是</span>OSGi<span style="font-family: 宋体">在企业应用领域的试金石，</span>2003<span style="font-family: 宋体">年</span>Eclipse3.0<span style="font-family: 宋体">做了一次架构上的调整，继续延用插件的架构思想，但是从</span>3.0<span style="font-family: 宋体">版之后，是基于</span>OSGi<span style="font-family: 宋体">的实现。也就是这一次的调整，推动了</span>Eclipse<span style="font-family: 宋体">的迅猛发展。</span></p>
<p style="text-indent: 24pt"><span style="font-family: 宋体">这是在桌面应用的成功示例，而</span>OSGi<span style="font-family: 宋体">的目标远不止于此，以其优秀的类加载机制，可以说，只需对其进行扩展，那么就可以目标瞄准任何一个领域。谈到企业应用，无可避免的要涉及</span>Web<span style="font-family: 宋体">应用，相信大多数人都在从事该领域的开发。</span>OSGi R4<span style="font-family: 宋体">版已明确提出了对</span>Web<span style="font-family: 宋体">的支持方式——当然，这种方式还是很有限的，这一点将在后面的文章中详细说明。</span></p>
<p style="text-indent: 24pt"><span style="font-family: 宋体">鉴于此，很多开源框架都已经或正准备发布支持</span>OSGi<span style="font-family: 宋体">的版本，比如</span>Spring DM<span style="font-family: 宋体">、</span>Struts1.8.1<span style="font-family: 宋体">、</span>CXF<span style="font-family: 宋体">等等，基本上日常所用的开源框架都发布了基于</span>OSGi<span style="font-family: 宋体">版本。另外，有不少应用服务器也已经基于</span>OSGi<span style="font-family: 宋体">进行实现，比如</span>WAS<span style="font-family: 宋体">从</span>6.1<span style="font-family: 宋体">版就已经是基于</span>OSGi<span style="font-family: 宋体">的实现，而</span>Spring<span style="font-family: 宋体">也在</span>2009<span style="font-family: 宋体">年推出了</span>Spring DM Server<span style="font-family: 宋体">，可见</span>OSGi<span style="font-family: 宋体">的吸引力还是很大的。</span></p>
<p style="text-indent: 24pt"><span style="font-family: 宋体">那么这一切将会为以后的开发带来什么影响呢？本文试图从</span>OSGi<span style="font-family: 宋体">和构件化开发的角度认识一下该问题。</span></p>
<p style="text-indent: 24pt">OSGi<span style="font-family: 宋体">的类加载机制非常优秀，为每个运行于其中的</span>bundle<span style="font-family: 宋体">创建了独立的类加载器环境，而运行于同一个</span>OSGi<span style="font-family: 宋体">框架内部的</span>bundle<span style="font-family: 宋体">之间不像</span>Web<span style="font-family: 宋体">服务器中的</span>Web<span style="font-family: 宋体">应用那样绝缘，它们之间是可以进行包依赖的，当然</span>OSGi<span style="font-family: 宋体">也提供了服务注册等相关机制，确保</span>bundle<span style="font-family: 宋体">之间的相互协作能力。而且</span>OSGi<span style="font-family: 宋体">支持</span>bundle<span style="font-family: 宋体">动态部署。所以，系统无需停机重启，就可以实现其内部的动态更新。</span></p>
<p style="text-indent: 24pt"><span style="font-family: 宋体">构件化开发的概念已经提了很多年了，似乎一直缺乏一种有效的机制对其进行支持。构件化开发为系统开发带来了很多好处，整个系统的开发可以按照模块的方式进行划分，从而按模块进行开发；系统由各模块之间拼装而成，通过代码一级的依赖或者服务依赖的方式；对于某个模块进行更新，只要保持接口不变，则可以实现对外界无影响。</span></p>
<p style="text-indent: 24pt"><span style="font-family: 宋体">由于缺乏有效的底层支持，构件化开发方式一直没有推行起来。由其对于</span>Web<span style="font-family: 宋体">应用而言，想要实现构件化开发，似乎更是无从谈起。</span></p>
<p style="text-indent: 24pt">OSGi<span style="font-family: 宋体">的出现，让这一事情有所转机。传统的</span>Web<span style="font-family: 宋体">应用开发过程中，可能大多数人的做法就是将一个大的</span>Web<span style="font-family: 宋体">应用按功能模块进行划分，通过包切分来实现模块化开发，但是各模块之间并没有从物理上隔离，只是以一种组织方式上的约束，使其从表面看上去是分离的。对于这种方式，动态更新某个模块也就无从谈起了。</span></p>
<p style="text-indent: 24pt"><span style="font-family: 宋体">而如果将</span>OSGi<span style="font-family: 宋体">引入</span>Web<span style="font-family: 宋体">应用，每个模块都对应于一个</span>bundle<span style="font-family: 宋体">，那么模块与模块之间则从物理上进行了隔离，能有效的将模块内部实现对外隐藏。模块之间的交互，可以通过接口的导出与引用来实现，对于未经导出的部分，对于其他模块是不可见的。另外，由于</span>OSGi<span style="font-family: 宋体">支持</span>bundle<span style="font-family: 宋体">的热部署，那就意味着，在当前</span>Web<span style="font-family: 宋体">应用未停机的情况下，可以对某个或某些模块（对应</span>OSGi<span style="font-family: 宋体">中的</span>bundle<span style="font-family: 宋体">）进行动态更新，而不影响整个应用的正常运行。</span></p>
<p style="text-indent: 24pt"><span style="font-family: 宋体">这种从物理上的有效隔离的方式，为重用带来了新的方式。以前代码一级的重用，一般都通过</span>Jar<span style="font-family: 宋体">包的形式进行，而这种方式存在上述的一些缺点，即封装性不够。而通过基于</span>OSGi<span style="font-family: 宋体">的</span>bundle<span style="font-family: 宋体">的形式，则可以有效隐藏内部实现，从包一级进行隐藏（这一点个人觉得可以作为</span>Java<span style="font-family: 宋体">封装性的一种扩展，以前的封装只能做到类一级，不知道未来是否会被</span>Java<span style="font-family: 宋体">规范吸收）。</span></p>
<p style="text-indent: 24pt"><span style="font-family: 宋体">就这一点而言，</span>OSGi<span style="font-family: 宋体">对构件化开发进行了很好的支持，当然</span>OSGi<span style="font-family: 宋体">并不为此而生。</span></p>
<p style="text-indent: 24pt"><span style="font-family: 宋体">以上所说的构件依赖都是基于</span>API<span style="font-family: 宋体">一级的，那么当然，我们也可以将</span>Web Service<span style="font-family: 宋体">等类型服务封装至构件当中，再结合</span>ESB<span style="font-family: 宋体">，是不是对</span>SOA<span style="font-family: 宋体">的一种更好实现呢！</span>ESB<span style="font-family: 宋体">的关注点在于服务，这是一种细粒度的，它并不考虑服务的封装、重用等方面——这些方面都由设计人员去把握。而结合</span>OSGi<span style="font-family: 宋体">，当然还需要其他设施的支持，比如</span>CXF<span style="font-family: 宋体">已经发布了基于</span>OSGi<span style="font-family: 宋体">的实现，可以将服务封装至一个</span>bundle<span style="font-family: 宋体">，以</span>bundle<span style="font-family: 宋体">为单元，向外界提供服务，这种服务即变成了一种粗粒度的——构件的特点之一。</span></p>
<p style="text-indent: 24pt"><span style="font-family: 宋体">综上所述，我相信，</span>OSGi<span style="font-family: 宋体">的发展，将会为构件化的开发方式带来福音。</span></p>
<p style="text-indent: 24pt"><span style="font-family: 宋体">引出话题：</span>OSGi<span style="font-family: 宋体">和</span>SCA<span style="font-family: 宋体">在很多方面有着异曲同工这妙，并且</span>SCA<span style="font-family: 宋体">的实现框架——</span>Tuscany<span style="font-family: 宋体">也对</span>OSGi<span style="font-family: 宋体">做了支持。这两者有互补特性，有时间将对这两者做一个对比研究。</span></p>
 <img src ="http://www.blogjava.net/benniaolk/aggbug/316738.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/benniaolk/" target="_blank">Dreava</a> 2010-03-28 11:49 <a href="http://www.blogjava.net/benniaolk/articles/316738.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OSGi初识</title><link>http://www.blogjava.net/benniaolk/articles/316739.html</link><dc:creator>Dreava</dc:creator><author>Dreava</author><pubDate>Sun, 28 Mar 2010 03:47:00 GMT</pubDate><guid>http://www.blogjava.net/benniaolk/articles/316739.html</guid><wfw:comment>http://www.blogjava.net/benniaolk/comments/316739.html</wfw:comment><comments>http://www.blogjava.net/benniaolk/articles/316739.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/benniaolk/comments/commentRss/316739.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/benniaolk/services/trackbacks/316739.html</trackback:ping><description><![CDATA[<p style="text-indent: 21pt">OSGi<span style="font-family: 宋体">诞生初期，其目的主要是能够灵活方便并远程管理互联的网络嵌入设备，</span>OSGi<span style="font-family: 宋体">联盟上对于</span>OSGi service platform<span style="font-family: 宋体">有这样一句解释：</span>The OSGi service platform delivers an open, common architecture for service providers, developers, software vendors, gateway operators and equipment vendors to develop, deploy and manage services in a coordinated fashion.<span style="font-family: 宋体">（</span>OSGi service platform<span style="font-family: 宋体">是一个开放并且提供通用接口标准的体系框架，基于这个体系框架，服务提供商，程序开发人员，软件提供商，服务网管运营商，设备提供商能够协调地联合起来开发，部署以及管理向用户提供的各种服务）。随着</span>OSGi<span style="font-family: 宋体">的发展，逐渐被引入到企业应用领域。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">目前，</span>OSGi<span style="font-family: 宋体">规范的最新版本为</span>R4.2<span style="font-family: 宋体">，有关该规范的详细情况请阅读</span>OSGi<span style="font-family: 宋体">实战的第</span>7<span style="font-family: 宋体">节——<a href="/Files/benniaolk/OSGi/OSGi初识/1.pdf"><span style="font-family: 宋体">深入</span>OSGi</a>。</span>OSGi<span style="font-family: 宋体">框架主要分为四部分：运行环境（</span>executionenvironment<span style="font-family: 宋体">）、模块（</span>Modules<span style="font-family: 宋体">）、生命周期管理（</span>Life Cycle<span style="font-family: 宋体">）、服务注册（</span>Service Registry<span style="font-family: 宋体">）。运行在</span>OSGi<span style="font-family: 宋体">环境中的是一个个的</span>Bundle<span style="font-family: 宋体">，也就是</span>Modules<span style="font-family: 宋体">的具体实现。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">对于每个</span>bundle<span style="font-family: 宋体">，都有各自的</span>ClassLoader<span style="font-family: 宋体">，在这一点上和传统的</span>Web<span style="font-family: 宋体">应用有相似之处，在传统的</span>Web<span style="font-family: 宋体">应用开发完成之后，都会将其部署在</span>Tomcat<span style="font-family: 宋体">、</span>Jboss<span style="font-family: 宋体">等服务器上，这些</span>Web<span style="font-family: 宋体">应用都有着各自的</span>ClassLoader<span style="font-family: 宋体">环境，而两者之间的区别在于，传统的</span>Web<span style="font-family: 宋体">应用无法做到资源的共享，因为它们是完全独立、隔离的。</span>OSGi<span style="font-family: 宋体">框架为</span>bundle<span style="font-family: 宋体">之间的协作提供了底层支持，通过在</span>bundle<span style="font-family: 宋体">的</span>MANIFEST.MF<span style="font-family: 宋体">文件中</span>Import-Package<span style="font-family: 宋体">、</span>Export-Package<span style="font-family: 宋体">等项，</span>bundle<span style="font-family: 宋体">之间就能相互共享资源及服务，在以后的博文中，我将给出一个具体的示例。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">由于</span>OSGi<span style="font-family: 宋体">具有良好的模块化结构，我个人认为这将为将来的软件开发方式带来很大的冲击，将更进一步推进模块化开发。目前</span>Web<span style="font-family: 宋体">应用的开发一般采用</span>SSH<span style="font-family: 宋体">框架，将整个应用大致分为</span>Web<span style="font-family: 宋体">（负责前台展现）、</span>Service<span style="font-family: 宋体">（负责业务逻辑处理）、</span>DAO<span style="font-family: 宋体">（负责数据持久化）、</span>Domain<span style="font-family: 宋体">（全局实体类）几个模块，而发布的时候，将被一起打成</span>WAR<span style="font-family: 宋体">包，部署至服务器上。如果采取</span>bundle<span style="font-family: 宋体">的形式，每个模块可以做为独立的</span>bundle<span style="font-family: 宋体">进行开发和部署，</span>bundle<span style="font-family: 宋体">之间的协作可以通过上述的方式进行，而这样带来的好处就是，一旦需要对某个模块进行更改，在保证依赖接口不变的前提下，就可以单独更改相应的</span>bundle<span style="font-family: 宋体">，再进行热部署即可，这样一来，好处是显而易见的，有效的分离了各个模块，减少了维护成本。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">由于采用</span>bundle<span style="font-family: 宋体">的形式，也增强了模块的复用性。这也是得益于</span>OSGi<span style="font-family: 宋体">良好的模块化方式。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">另外一个很重要的点就是</span>OSGi<span style="font-family: 宋体">具备热拔插特性，</span>bundle<span style="font-family: 宋体">的安装、启动、停止、卸载都可以在运行时指定，并且可以随时更改。这样一来，我们就可以做到无需重启整个应用，而只对需要更改的部分进行升级或打补丁即可。</span>Bundl<span style="font-family: 宋体">的状态图转换如下图所示：<br />
</span></p>
<p style="text-align: center" align="center"><span style="font-family: 黑体"><img height="372" alt="" src="http://www.blogjava.net/images/blogjava_net/benniaolk/OSGi/OSGi初识/1.JPG" width="458" border="0" /><br />
图</span> 1 OSGi bundle<span style="font-family: 黑体">状态转换图</span></p>
<p style="text-indent: 21.2pt"><span style="font-family: 宋体">以上将</span>OSGi<span style="font-family: 宋体">的一些基本的，但也是很重要的东西大概介绍了一下，在以后的博文中逐步深入吧。以上都是关于</span>OSGi<span style="font-family: 宋体">原理性的东西，那么实现该规范的有哪些产品呢？最有名的应该要数</span>Eclipse<span style="font-family: 宋体">的</span>Equinox<span style="font-family: 宋体">框架了，在网上查资料见有人说过，</span>Eclipse3.0<span style="font-family: 宋体">的那一次升级把自身的构架做了一次非常大的调整，其主要原因就是采用了</span>OSGi<span style="font-family: 宋体">框架，更好的支持了</span>Eclipse<span style="font-family: 宋体">的插件体系。另外还有</span>Felix<span style="font-family: 宋体">、</span>knopflerfish<span style="font-family: 宋体">等。</span></p>
<p style="text-indent: 21.2pt"><span style="font-family: 宋体">不过话说回来，尽管</span>OSGi<span style="font-family: 宋体">有很多好处，但是现在主要还是应用在服务器端，如现在的应用服务器基本上都采用</span>OSGi<span style="font-family: 宋体">的框架，而真正的应用市场仍处理起步阶段，这和</span>OSGi<span style="font-family: 宋体">的生态环境还不成熟，可喜的是</span>Spring<span style="font-family: 宋体">推出了其</span>Spring DM<span style="font-family: 宋体">和</span>SpringSource DM Server<span style="font-family: 宋体">，前者能够很方便发布和引用服务，并且与</span>Spring Framework<span style="font-family: 宋体">平台相融合，将</span>OSGi<span style="font-family: 宋体">的</span>bundle context<span style="font-family: 宋体">与</span>Spring&nbsp;applicationContext<span style="font-family: 宋体">融合在一起，大大方便了</span>OSGi<span style="font-family: 宋体">的应用。后者是</span>OSGi bundle<span style="font-family: 宋体">的运行环境，是一个将</span>Equinox<span style="font-family: 宋体">和</span>Tomcat<span style="font-family: 宋体">融合在一起的服务器。在以后的博文中将详细介绍这些内容。</span></p>
 <img src ="http://www.blogjava.net/benniaolk/aggbug/316739.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/benniaolk/" target="_blank">Dreava</a> 2010-03-28 11:47 <a href="http://www.blogjava.net/benniaolk/articles/316739.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>