﻿<?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-Chasing an OSGi vision</title><link>http://www.blogjava.net/Ferrari4000/</link><description>OSGi技术的研究和讨论</description><language>zh-cn</language><lastBuildDate>Fri, 09 Jan 2009 06:13:06 GMT</lastBuildDate><pubDate>Fri, 09 Jan 2009 06:13:06 GMT</pubDate><ttl>60</ttl><item><title>OSGi介绍（七）bundle和service(续)</title><link>http://www.blogjava.net/Ferrari4000/archive/2007/07/21/131670.html</link><dc:creator>勤劳的蜜蜂</dc:creator><author>勤劳的蜜蜂</author><pubDate>Sat, 21 Jul 2007 14:28:00 GMT</pubDate><guid>http://www.blogjava.net/Ferrari4000/archive/2007/07/21/131670.html</guid><wfw:comment>http://www.blogjava.net/Ferrari4000/comments/131670.html</wfw:comment><comments>http://www.blogjava.net/Ferrari4000/archive/2007/07/21/131670.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Ferrari4000/comments/commentRss/131670.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Ferrari4000/services/trackbacks/131670.html</trackback:ping><description><![CDATA[<p>接上一篇的例子，为了更具体一点，我们考虑这样的case,<br>假设房地产开发商construction A采纳了规划公司design A的方案，打算建造公寓类型的房子CityApartment<br>然后客户A买了一套房子</p>
<p>用ooa方式分析这个case，<br>我抽象这几个实体：规划公司，图纸类型，开发商，房子，买房人<br>然后描述这几件事情：开发商选择设计图纸，盖楼然后销售；买房人根据图纸买房并使用房子</p>
<p>下面是我用java语言来简单描述它：</p>
<p>design A 公司</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><span style="COLOR: #0000ff">package</span><span style="COLOR: #000000">&nbsp;design.a;<br><img id=Codehighlighter1_38_53_Open_Image onclick="this.style.display='none'; Codehighlighter1_38_53_Open_Text.style.display='none'; Codehighlighter1_38_53_Closed_Image.style.display='inline'; Codehighlighter1_38_53_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_38_53_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_38_53_Closed_Text.style.display='none'; Codehighlighter1_38_53_Open_Image.style.display='inline'; Codehighlighter1_38_53_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">interface</span><span style="COLOR: #000000">&nbsp;Apartment&nbsp;</span><span id=Codehighlighter1_38_53_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"></span><span id=Codehighlighter1_38_53_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><img src="http://www.blogjava.net/Images/dot.gif">..</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">方法省略先</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top></span><span style="COLOR: #000000">}</span></span></div>
<p>&nbsp;</p>
<p>开发商construction A</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><span style="COLOR: #0000ff">package</span><span style="COLOR: #000000">&nbsp;construction.a<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;design.a.</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">开发商要按照图纸盖楼</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_97_111_Open_Image onclick="this.style.display='none'; Codehighlighter1_97_111_Open_Text.style.display='none'; Codehighlighter1_97_111_Closed_Image.style.display='inline'; Codehighlighter1_97_111_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_97_111_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_97_111_Closed_Text.style.display='none'; Codehighlighter1_97_111_Open_Image.style.display='inline'; Codehighlighter1_97_111_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;CityApartment&nbsp;</span><span style="COLOR: #0000ff">implements</span><span style="COLOR: #000000">&nbsp;Apartment&nbsp;</span><span id=Codehighlighter1_97_111_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"></span><span id=Codehighlighter1_97_111_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><img src="http://www.blogjava.net/Images/dot.gif">.</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">方法省略先</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top></span><span style="COLOR: #000000">}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_159_162_Open_Image onclick="this.style.display='none'; Codehighlighter1_159_162_Open_Text.style.display='none'; Codehighlighter1_159_162_Closed_Image.style.display='inline'; Codehighlighter1_159_162_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_159_162_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_159_162_Closed_Text.style.display='none'; Codehighlighter1_159_162_Open_Image.style.display='inline'; Codehighlighter1_159_162_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Construction&nbsp;</span><span style="COLOR: #0000ff">implements</span><span style="COLOR: #000000">&nbsp;BundleActivator</span><span id=Codehighlighter1_159_162_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"></span><span id=Codehighlighter1_159_162_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span></div>
<p><br>客户 costumer A</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><span style="COLOR: #0000ff">package</span><span style="COLOR: #000000">&nbsp;customer.a<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;design.a.</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">客户要按照图纸选择房子</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_95_109_Open_Image onclick="this.style.display='none'; Codehighlighter1_95_109_Open_Text.style.display='none'; Codehighlighter1_95_109_Closed_Image.style.display='inline'; Codehighlighter1_95_109_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_95_109_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_95_109_Closed_Text.style.display='none'; Codehighlighter1_95_109_Open_Image.style.display='inline'; Codehighlighter1_95_109_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Customer&nbsp;</span><span style="COLOR: #0000ff">implements</span><span style="COLOR: #000000">&nbsp;BundleActivator&nbsp;</span><span id=Codehighlighter1_95_109_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"></span><span id=Codehighlighter1_95_109_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><img src="http://www.blogjava.net/Images/dot.gif">.</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">方法省略先</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top></span><span style="COLOR: #000000">}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span></div>
<p><br>然后我们把他们分别做成bundle<br>Bundle A : design A<br>其manifest中这样描述<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><span style="COLOR: #000000">BundleSymbolicName:&nbsp;design&nbsp;A<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>Export</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">Package:&nbsp;design.a<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span></div>
<p><br>Bundle B : construction A<br>其manifest中这样描述</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><span style="COLOR: #000000">BundleSymbolicName:&nbsp;construction&nbsp;A<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>Import</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">Package:&nbsp;design.a<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>Bundle</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">Activator:&nbsp;construction.a.Construction<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span></div>
<p><br>Bundle C : customer C<br>其manifest中这样描述</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><span style="COLOR: #000000">BundleSymbolicName:&nbsp;customer&nbsp;C<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>Import</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">Package:&nbsp;design.a<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>Bundle</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">Activator:&nbsp;customer.c.Customer<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span></div>
<p><br><br>这样，装入到framework后，framework就会把BundlB和C与BundleA关联起来，正好描述开发商A选择design A的图纸，客户A也不得不选择design A的图纸啦<br>可是，单从这里，我们看不出来，开发商和客户拿同一份图纸干什么。那我们得必须在BundleB和C的实现里面写点东西来说明。</p>
<p>这里给出开发商construction.a.Construction的伪代码：</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_46_522_Open_Image onclick="this.style.display='none'; Codehighlighter1_46_522_Open_Text.style.display='none'; Codehighlighter1_46_522_Closed_Image.style.display='inline'; Codehighlighter1_46_522_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_46_522_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_46_522_Closed_Text.style.display='none'; Codehighlighter1_46_522_Open_Image.style.display='inline'; Codehighlighter1_46_522_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Construction&nbsp;</span><span style="COLOR: #0000ff">implements</span><span style="COLOR: #000000">&nbsp;BundleActivator&nbsp;</span><span id=Codehighlighter1_46_522_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"></span><span id=Codehighlighter1_46_522_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_90_520_Open_Image onclick="this.style.display='none'; Codehighlighter1_90_520_Open_Text.style.display='none'; Codehighlighter1_90_520_Closed_Image.style.display='inline'; Codehighlighter1_90_520_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_90_520_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_90_520_Closed_Text.style.display='none'; Codehighlighter1_90_520_Open_Image.style.display='inline'; Codehighlighter1_90_520_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&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)</span><span id=Codehighlighter1_90_520_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"></span><span id=Codehighlighter1_90_520_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;CityApartment&nbsp;apartment&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;Hashtable&nbsp;properties&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">;<br><img id=Codehighlighter1_188_498_Open_Image onclick="this.style.display='none'; Codehighlighter1_188_498_Open_Text.style.display='none'; Codehighlighter1_188_498_Closed_Image.style.display='inline'; Codehighlighter1_188_498_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_188_498_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_188_498_Closed_Text.style.display='none'; Codehighlighter1_188_498_Open_Image.style.display='inline'; Codehighlighter1_188_498_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">;&nbsp;i&nbsp;</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)</span><span id=Codehighlighter1_188_498_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"></span><span id=Codehighlighter1_188_498_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;properties&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Hashtable();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;properties.put(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">price</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Integer(</span><span style="COLOR: #000000">1000</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">));</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">开发商为房子定价</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;apartment&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;CityApartment();</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">一套房子盖好<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">把房子按照公寓注册出去并打广告，等待客户来购买，framework就相当于一个售楼处兼房屋中介</span><span style="COLOR: #008000"><br><img id=Codehighlighter1_434_441_Open_Image onclick="this.style.display='none'; Codehighlighter1_434_441_Open_Text.style.display='none'; Codehighlighter1_434_441_Closed_Image.style.display='inline'; Codehighlighter1_434_441_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_434_441_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_434_441_Closed_Text.style.display='none'; Codehighlighter1_434_441_Open_Image.style.display='inline'; Codehighlighter1_434_441_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;context.registerService(Apartment.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">.getName()</span><span id=Codehighlighter1_434_441_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_434_441_Open_Text><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">公寓类型</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000">,apartment</span><span id=Codehighlighter1_452_463_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_452_463_Open_Text><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">房子作为服务对象</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000">,properties</span><span id=Codehighlighter1_475_488_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_475_488_Open_Text><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">与房子相关的附带信息</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">这样开发商一共注册一百套房子</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top></span><span style="COLOR: #000000">&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span></div>
<p><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 id=Codehighlighter1_42_344_Open_Image onclick="this.style.display='none'; Codehighlighter1_42_344_Open_Text.style.display='none'; Codehighlighter1_42_344_Closed_Image.style.display='inline'; Codehighlighter1_42_344_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_42_344_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_42_344_Closed_Text.style.display='none'; Codehighlighter1_42_344_Open_Image.style.display='inline'; Codehighlighter1_42_344_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Customer&nbsp;</span><span style="COLOR: #0000ff">implements</span><span style="COLOR: #000000">&nbsp;BundleActivator&nbsp;</span><span id=Codehighlighter1_42_344_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"></span><span id=Codehighlighter1_42_344_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_85_342_Open_Image onclick="this.style.display='none'; Codehighlighter1_85_342_Open_Text.style.display='none'; Codehighlighter1_85_342_Closed_Image.style.display='inline'; Codehighlighter1_85_342_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_85_342_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_85_342_Closed_Text.style.display='none'; Codehighlighter1_85_342_Open_Image.style.display='inline'; Codehighlighter1_85_342_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&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)</span><span id=Codehighlighter1_85_342_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"></span><span id=Codehighlighter1_85_342_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;Apartment&nbsp;apartment&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;ServiceReference&nbsp;ref&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;context.getServiceReference(Apartment.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">.getName,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">(price=1050)</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">先签署购房合同，而且指明选择Apartment类型,价格为1050的房子。</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;apartment&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(Apartment)context.getService(ref);</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">然后买到房子<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">买房人就可以使用房子apartment对象进行日常生活了</span><span style="COLOR: #008000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top></span><span style="COLOR: #000000">&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span></div>
<p><br>这样，我们就很清楚的看出，Design A为Construction A和Customer A提供了共同的Apartment定义，才使得他们有交易的可能。于此同时，Construction A和Customer A之间的耦合是非常松的，因为，如果有另外一个开发商onstruction B加入进来也构造了Apartment的对象，Customer就可以通过改变选择条件，轻易的获得B的房子，而客户本身不关心房子是A还是B盖的，这个是典型的面向对象的多态应用。</p>
<p>总的说来，Bundle在framework的帮助下，使得其他bundle使用其类型定义成为可能。service就是在这些共享的类型定义基础上产生的具体对象，而使用这些service对象的bundle，必然也是对应共享类型的使用者。<br>这种类型共享，在osgi里面叫做"class space". framework运行时通过关联bundle之间的类型定义，可以构成一个或多个"class space"，而某个bundle在framework里面，只能处在一个"class space"里面，不能同时出现在多个"class space"中。<br>怎么理解这个话呢？请看下一篇，外星人入侵了。</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/Ferrari4000/aggbug/131670.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Ferrari4000/" target="_blank">勤劳的蜜蜂</a> 2007-07-21 22:28 <a href="http://www.blogjava.net/Ferrari4000/archive/2007/07/21/131670.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OSGi 介绍（七）bundle和service的关系</title><link>http://www.blogjava.net/Ferrari4000/archive/2007/07/16/130692.html</link><dc:creator>勤劳的蜜蜂</dc:creator><author>勤劳的蜜蜂</author><pubDate>Mon, 16 Jul 2007 15:31:00 GMT</pubDate><guid>http://www.blogjava.net/Ferrari4000/archive/2007/07/16/130692.html</guid><wfw:comment>http://www.blogjava.net/Ferrari4000/comments/130692.html</wfw:comment><comments>http://www.blogjava.net/Ferrari4000/archive/2007/07/16/130692.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/Ferrari4000/comments/commentRss/130692.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Ferrari4000/services/trackbacks/130692.html</trackback:ping><description><![CDATA[<p>osgi系列已经发表了有将近2年的时间了，很高兴这期间得到了许多朋友的关注，你们和我的讨论切磋都让我兴奋无比。而过去很长的时间里，由于灵感枯竭外加精力有限，不能给大家分享更多osgi的精彩，实在辜负大家的期望，还请谅解。不过，根据这段时间大家和我私下的讨论，发现很多人都苦恼于分不清楚bundle和service的关系，而我的osgi 5-6又臭又长，而且还非常依赖技术，实在是坑害入门者的必备武器。这个不足，犹如头上方圆半尺盘旋的苍蝇，困扰着我，解释的邮件也不知写多少，估计收效甚微。于是我决定再次出山，写一个惊世骇俗的分析文章，力图让更多读者都能够把这两个疯马牛理清楚。</p>
<p>开讲之前，还是用老办法，给大家举个例子。放心，这个例子一点都不技术，而且我相信你可能比我还清楚。大家都知道房地产商是怎么运作楼盘的吧。据我浅显的认识，他们都会先进行一些图纸上的规划，里面包含小区的整体规模，楼房外观以及广大疾苦民众最为关心和渴求的户型图。据说，很多房地产商在搞定政府某些关键部门（个人意见仅供参考）拿到一块地后，根本不用费心思去自己规划这些自己都一窍不通的东西，只要请一个有资质的第三方公司写写画画，甚至照搬某西方发达国家的某社区概念，冠于中国特色云云，就能使广大民众趋之若鹜，倾囊抢购。ok，你可能受不了我又愤世嫉俗了，这个到底和osgi有啥关系？别着急，天色已经很晚，下次某个时间请继续关注osgi(七)续，其间，请大家先考虑一下，如何用ooa的方式来描述人们如何购房，以及在房子里进行日常生活这样的简单场景。</p>
<img src ="http://www.blogjava.net/Ferrari4000/aggbug/130692.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Ferrari4000/" target="_blank">勤劳的蜜蜂</a> 2007-07-16 23:31 <a href="http://www.blogjava.net/Ferrari4000/archive/2007/07/16/130692.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OSGi on mobile phone !</title><link>http://www.blogjava.net/Ferrari4000/archive/2007/05/14/117256.html</link><dc:creator>勤劳的蜜蜂</dc:creator><author>勤劳的蜜蜂</author><pubDate>Mon, 14 May 2007 02:11:00 GMT</pubDate><guid>http://www.blogjava.net/Ferrari4000/archive/2007/05/14/117256.html</guid><wfw:comment>http://www.blogjava.net/Ferrari4000/comments/117256.html</wfw:comment><comments>http://www.blogjava.net/Ferrari4000/archive/2007/05/14/117256.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Ferrari4000/comments/commentRss/117256.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Ferrari4000/services/trackbacks/117256.html</trackback:ping><description><![CDATA[<p>如果你一直关注osgi在embedded的发展,并且还能到旧金山参加正在举行的java one,那我真是羡慕死你了.<br><br>Nokia在她的N800上demo运行了osgi(此消息来源于david beers对BJ在osgi alliance blog上的评论,关于demo可以看这个link <a href="http://thehereweb.googlepages.com/">http://thehereweb.googlepages.com/</a>)<br>同时美国运行商Sprint也宣布采用osgi的手机平台将会在年底面世.多么值得期待的事情!</p>
<img src ="http://www.blogjava.net/Ferrari4000/aggbug/117256.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Ferrari4000/" target="_blank">勤劳的蜜蜂</a> 2007-05-14 10:11 <a href="http://www.blogjava.net/Ferrari4000/archive/2007/05/14/117256.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>framework implementation updated</title><link>http://www.blogjava.net/Ferrari4000/archive/2006/09/16/70100.html</link><dc:creator>勤劳的蜜蜂</dc:creator><author>勤劳的蜜蜂</author><pubDate>Sat, 16 Sep 2006 15:40:00 GMT</pubDate><guid>http://www.blogjava.net/Ferrari4000/archive/2006/09/16/70100.html</guid><wfw:comment>http://www.blogjava.net/Ferrari4000/comments/70100.html</wfw:comment><comments>http://www.blogjava.net/Ferrari4000/archive/2006/09/16/70100.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Ferrari4000/comments/commentRss/70100.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Ferrari4000/services/trackbacks/70100.html</trackback:ping><description><![CDATA[
		<p>瞎整了半年多，克服了重重困难，终于把原来framework做了更新，如果有兴趣，还可以按照原来的Link下载。<br />framework下载后，解压并运行startframework.bat就可以启动framework了。<br />目前该framework只支持在内存中存储bundle.<br /><br />另外，多增加了一个管理bundle，它为framework提供了简单的图形化操作界面，可以在这里下载。</p>
		<p>
				<a href="/Files/Ferrari4000/bundlemanagement.zip">http://www.blogjava.net/Files/Ferrari4000/bundlemanagement.zip</a>
				<br />
				<br />下载后，最好先把名字改为bundlemanagement.jar<br />然后可以这样安装，假设该文件下载到d:\bundles下，则可以在framework的shell下输入<br />in file:d:/bundles/bundlemanagement.jar<br />安装该bundle，安装成功后输入stt 1（注意：1是数字一），启动该bundle就可以出现图形操作界面了。<br /><br />图形界面提供bundle的安装（只支持本地安装），启动，停止，升级和删除等简单功能。<br />其他功能会在后面陆续增加。目前这个bundle只能运行在j2se环境下。<br /><br />给的源代码没有很好的build文件，等我有时间了，再写一个。<br /><br />感谢毕嘉兄弟的支持，他帮助设计了bundle存储模块以及实现了bundle在内存存储的第一版。<br /><br />有啥问题，可以直接给我发邮件，<a href="mailto:jerrylee.li@gmail.com">jerrylee.li@gmail.com</a><br /><br /></p>
<img src ="http://www.blogjava.net/Ferrari4000/aggbug/70100.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Ferrari4000/" target="_blank">勤劳的蜜蜂</a> 2006-09-16 23:40 <a href="http://www.blogjava.net/Ferrari4000/archive/2006/09/16/70100.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OSGi的曙光？</title><link>http://www.blogjava.net/Ferrari4000/archive/2006/03/03/33453.html</link><dc:creator>勤劳的蜜蜂</dc:creator><author>勤劳的蜜蜂</author><pubDate>Fri, 03 Mar 2006 05:51:00 GMT</pubDate><guid>http://www.blogjava.net/Ferrari4000/archive/2006/03/03/33453.html</guid><wfw:comment>http://www.blogjava.net/Ferrari4000/comments/33453.html</wfw:comment><comments>http://www.blogjava.net/Ferrari4000/archive/2006/03/03/33453.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/Ferrari4000/comments/commentRss/33453.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Ferrari4000/services/trackbacks/33453.html</trackback:ping><description><![CDATA[前两天，看到Peter的blog里说，由ibm牵头发起了jsr291（<A href="http://www.jcp.org/en/jsr/detail?id=291">http://www.jcp.org/en/jsr/detail?id=291</A>），<BR>要把osgi的core应用到目前的j2se上，以填补jsr277发布前的需求空白。<BR><BR>osgi和277的pk开始了！我投osgi一票，呵呵，你买谁？<BR><img src ="http://www.blogjava.net/Ferrari4000/aggbug/33453.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Ferrari4000/" target="_blank">勤劳的蜜蜂</a> 2006-03-03 13:51 <a href="http://www.blogjava.net/Ferrari4000/archive/2006/03/03/33453.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OSGi Alliance开设面向公众的邮件列表</title><link>http://www.blogjava.net/Ferrari4000/archive/2006/02/16/30919.html</link><dc:creator>勤劳的蜜蜂</dc:creator><author>勤劳的蜜蜂</author><pubDate>Thu, 16 Feb 2006 02:20:00 GMT</pubDate><guid>http://www.blogjava.net/Ferrari4000/archive/2006/02/16/30919.html</guid><wfw:comment>http://www.blogjava.net/Ferrari4000/comments/30919.html</wfw:comment><comments>http://www.blogjava.net/Ferrari4000/archive/2006/02/16/30919.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Ferrari4000/comments/commentRss/30919.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Ferrari4000/services/trackbacks/30919.html</trackback:ping><description><![CDATA[<P>继开设Blog后（<A href="http://www.osgi.org/blog/index.html">http://www.osgi.org/blog/index.html</A>），昨天OSGi Alliance又宣布开设一个public的mail list，每个对OSGi感兴趣的人都可以加入到这个列表中，通过这个列表可以讯问OSGi的相关的各种问题以及订阅列表的邮件。<BR>请到<A href="http://bundles.osgi.org/mailman/listinfo/osgi-dev">http://bundles.osgi.org/mailman/listinfo/osgi-dev</A>这里注册。<BR><BR>下面是BJ Hargrave的代表OSGi Alliance发的announcement<BR><BR><BR>Hello,</P>
<P>As part of the OSGi evangelism work, I would like to announce that OSGi now has a new public mail list for OSGi technical questions and discussion. This mail list is a public list and is open to anyone to participate. This new list is mainly for non-members to discuss OSGi technology and ask question about the technology. ......</P>
<P>The new mail list address is:</P>
<P><A href="mailto:osgi-dev@bundles.osgi.org">osgi-dev@bundles.osgi.org</A></P>
<P>You can subscribe to the list here: <BR><A href="http://bundles.osgi.org/mailman/listinfo/osgi-dev">http://bundles.osgi.org/mailman/listinfo/osgi-dev</A> or by sending an e-mail to <A href="mailto:osgi-dev-subscribe@bundles.osgi.org">osgi-dev-subscribe@bundles.osgi.org</A>.</P>
<P>So please go ahead and subscribe to the new osgi-dev mail list. Your participation there can help educate others about the OSGi technology.</P>
<P>BJ Hargrave<BR>Senior Technical Staff Member, IBM<BR>OSGi Fellow and CTO of the OSGi Alliance</P><img src ="http://www.blogjava.net/Ferrari4000/aggbug/30919.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Ferrari4000/" target="_blank">勤劳的蜜蜂</a> 2006-02-16 10:20 <a href="http://www.blogjava.net/Ferrari4000/archive/2006/02/16/30919.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>framework implementation</title><link>http://www.blogjava.net/Ferrari4000/archive/2006/02/15/30737.html</link><dc:creator>勤劳的蜜蜂</dc:creator><author>勤劳的蜜蜂</author><pubDate>Wed, 15 Feb 2006 01:15:00 GMT</pubDate><guid>http://www.blogjava.net/Ferrari4000/archive/2006/02/15/30737.html</guid><wfw:comment>http://www.blogjava.net/Ferrari4000/comments/30737.html</wfw:comment><comments>http://www.blogjava.net/Ferrari4000/archive/2006/02/15/30737.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.blogjava.net/Ferrari4000/comments/commentRss/30737.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Ferrari4000/services/trackbacks/30737.html</trackback:ping><description><![CDATA[<P>这里是我目前的成果。<BR><A href="/Files/Ferrari4000/framework.zip">http://www.blogjava.net/Files/Ferrari4000/framework.zip</A>包含了framework的jar文件。<BR>解压后，直接运行.bat文件就可以了。这个framework实现了r4core的大部分api（除一些支持local和安全的外，secrurity admin和conditional permission这两个服务也没有实现，url service也没有实现），输入help可以看到可以运行的命令（不过全是英文的，还是我写的，将就一下吧）。<BR><BR><A href="/Files/Ferrari4000/src.zip">http://www.blogjava.net/Files/Ferrari4000/src.zip</A>包含所有源码。代码有点乱，hoho<BR><BR><STRONG><FONT style="BACKGROUND-COLOR: #ffffff" color=#ff0000>要成功编译代码，您还需要下载这个<A HREF="/Files/Ferrari4000/osgi.rar">http://www.blogjava.net/Files/Ferrari4000/osgi.rar</A></FONT></STRONG><BR><FONT style="BACKGROUND-COLOR: #ffffff"><FONT color=#ff0000><STRONG>解压并后得到4个jar，并把他们放入到build path中，import顺序保证它们优先于jre就可以了。</STRONG><BR></FONT></FONT><BR>我打算重新编写了。把framework的实现重新规划一下，然后实现core的所有内容，进而再实现cmpn的所有服务。<BR>如果你对开发osgi framework感兴趣，一起来吧！<BR><BR>给我发信：<A href="mailto:jerrylee.li@gmail.com">jerrylee.li@gmail.com</A><BR></P><img src ="http://www.blogjava.net/Ferrari4000/aggbug/30737.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Ferrari4000/" target="_blank">勤劳的蜜蜂</a> 2006-02-15 09:15 <a href="http://www.blogjava.net/Ferrari4000/archive/2006/02/15/30737.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OSGi介绍（六）OSGi的service</title><link>http://www.blogjava.net/Ferrari4000/archive/2006/02/14/30626.html</link><dc:creator>勤劳的蜜蜂</dc:creator><author>勤劳的蜜蜂</author><pubDate>Tue, 14 Feb 2006 08:08:00 GMT</pubDate><guid>http://www.blogjava.net/Ferrari4000/archive/2006/02/14/30626.html</guid><wfw:comment>http://www.blogjava.net/Ferrari4000/comments/30626.html</wfw:comment><comments>http://www.blogjava.net/Ferrari4000/archive/2006/02/14/30626.html#Feedback</comments><slash:comments>13</slash:comments><wfw:commentRss>http://www.blogjava.net/Ferrari4000/comments/commentRss/30626.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Ferrari4000/services/trackbacks/30626.html</trackback:ping><description><![CDATA[<DIV>在给出采用service方式实现的“扶贫助手”之前，我们稍微回顾一下上一篇的成果。<BR>在（五）中，我们看到程序被分成多个bundle后，程序的模块程度得到提高，而控制模块间的耦合度由Import-Package和Export-Package来控制，相对比较灵活。另一方面程序的更新和升级的粒度变小了。谁都知道只更新部分要比全部更新强，尤其当更新发生在一些需要建立昂贵的连接时，细粒度会节省不少花销。除了这些，我们看不到其他新鲜的东西。说白了，也就是挖空心思想一些design pattern来划分程序模块。</DIV>
<DIV>&nbsp;</DIV>
<DIV>好了，马上就新鲜了。下面你会看到通过采用service方式来改造（五）中的程序，gui bundle在某些情况下不用重新启动，就能直接某些适应需求的变更！<BR>先给出model bundle的代码，该bundle包含两个java package，分别是:<BR>com.bajie.test.family.model<BR>com.bajie.test.family.model.impl</DIV>
<DIV>在com.bajie.test.family.model这个package中包含如下的class和interface:</DIV>
<DIV>package com.bajie.test.family.model;</DIV>
<DIV>import java.util.List;</DIV>
<DIV>import javax.swing.table.AbstractTableModel;</DIV>
<DIV>public abstract class FamilyInfoDatabase extends AbstractTableModel{<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; public abstract void sort(SortingFamilyInfoCriteria sortField) throws IllegalArgumentException;<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; public abstract void addEntry(List columns, List values) throws IllegalArgumentException;<BR>&nbsp;&nbsp;&nbsp; public abstract void deleteEntry(String familyName);<BR>&nbsp;&nbsp;&nbsp; public abstract void update(String familyName,List columns, List values)throws IllegalArgumentException;</DIV>
<DIV>}</DIV>
<DIV><BR>这是database的model，与（五）定义成interface不同，我们直接让它继承了AbstractTableModel，这是因为我们希望当数据或显示需求变化时，gui上的JTable能获得通知，并显示更新的结果。SortingFamilyInfoCriteria这个类型下文会给出说明。</DIV>
<DIV>&nbsp;</DIV>
<DIV>package com.bajie.test.family.model;</DIV>
<DIV>public class FamilyInfoEntry {</DIV>
<DIV>&nbsp;&nbsp;&nbsp; private String familyName;<BR>&nbsp;&nbsp;&nbsp; private int population;<BR>&nbsp;&nbsp;&nbsp; private int incomePerYear;<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; public FamilyInfoEntry(String familyName,int population,int income){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.familyName = familyName;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.population = population;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.incomePerYear = income;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; public String getFamilyName() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return familyName;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; public int getIncomePerYear() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return incomePerYear;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; public int getPopulation() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return population;<BR>&nbsp;&nbsp;&nbsp; }<BR>}</DIV>
<DIV><BR>这个类的结构和在（五）中完全一样，用来纪录一条家庭信息。唯一不同的是，在（五）中我们把它放入了实现(.impl)package中，在后面给出bundle的manifest文件时，我将解释为什么要这样改。</DIV>
<DIV>&nbsp;</DIV>
<DIV>package com.bajie.test.family.model;</DIV>
<DIV>public interface FamilyInfoColumn {</DIV>
<DIV>&nbsp;&nbsp;&nbsp; public Object getColumnValue(FamilyInfoEntry entry);<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; public String getColumnName();<BR>}<BR>这个类用来描述table中的某个列。</DIV>
<DIV>package com.bajie.test.family.model;</DIV>
<DIV>import java.util.Comparator;<BR>public interface SortingFamilyInfoCriteria extends Comparator{<BR>&nbsp;&nbsp;&nbsp; public String getSortFieldString();<BR>}<BR>这个类将用于对家庭纪录按某一列的值进行排序。</DIV>
<DIV>在com.bajie.test.family.model.impl这个package中包含上面抽象类和interface的实现：</DIV>
<DIV>package com.bajie.test.family.model.impl;</DIV>
<DIV>import java.util.Arrays;<BR>import java.util.LinkedList;<BR>import java.util.List;</DIV>
<DIV>import org.osgi.framework.BundleActivator;<BR>import org.osgi.framework.BundleContext;<BR>import org.osgi.framework.Constants;<BR>import org.osgi.framework.ServiceEvent;<BR>import org.osgi.framework.ServiceListener;<BR>import org.osgi.framework.ServiceReference;</DIV>
<DIV>import com.bajie.test.family.model.FamilyInfoColumn;<BR>import com.bajie.test.family.model.FamilyInfoDatabase;<BR>import com.bajie.test.family.model.FamilyInfoEntry;<BR>import com.bajie.test.family.model.SortingFamilyInfoCriteria;</DIV>
<DIV>public class FamilyDatabase extends FamilyInfoDatabase implements&nbsp; BundleActivator,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ServiceListener {<BR>&nbsp;&nbsp;&nbsp; private LinkedList familyEntryList = new LinkedList();</DIV>
<DIV>&nbsp;&nbsp;&nbsp; private Object[] sortedValues = null;</DIV>
<DIV>&nbsp;&nbsp;&nbsp; private LinkedList columns = new LinkedList();</DIV>
<DIV>&nbsp;&nbsp;&nbsp; private BundleContext context;</DIV>
<DIV>&nbsp;&nbsp;&nbsp; public int getColumnCount() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return this.columns.size();<BR>&nbsp;&nbsp;&nbsp; }</DIV>
<DIV>&nbsp;&nbsp;&nbsp; public String getColumnName(int index) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ((FamilyInfoColumn)columns.get(index)).getColumnName();<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; public Object getValueAt(int row, int column) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FamilyInfoEntry entry = (FamilyInfoEntry) this.sortedValues[row];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(column &gt;= this.familyEntryList.size()){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ((FamilyInfoColumn) this.columns.get(column))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .getColumnValue(entry);<BR>&nbsp;&nbsp;&nbsp; }</DIV>
<DIV>&nbsp;&nbsp;&nbsp; public int getRowCount() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return this.familyEntryList.size();<BR>&nbsp;&nbsp;&nbsp; }</DIV>
<DIV>&nbsp;&nbsp;&nbsp; public void addEntry(List columns, List values)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throws IllegalArgumentException {<BR>&nbsp;&nbsp;&nbsp; }</DIV>
<DIV>&nbsp;&nbsp;&nbsp; public void deleteEntry(String familyName) {<BR>&nbsp;&nbsp;&nbsp; }</DIV>
<DIV>&nbsp;&nbsp;&nbsp; public void update(String familyName, List columns, List values)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throws IllegalArgumentException {<BR>&nbsp;&nbsp;&nbsp; }</DIV>
<DIV>&nbsp;&nbsp;&nbsp; public void sort(SortingFamilyInfoCriteria sortField) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Arrays.sort(this.sortedValues, sortField);<BR>&nbsp;&nbsp;&nbsp; }</DIV>
<DIV>&nbsp;&nbsp;&nbsp; public void start(BundleContext context) throws Exception {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.context = context;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.familyEntryList.add(new FamilyInfoEntry("Zhang", 3, 1200));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.familyEntryList.add(new FamilyInfoEntry("Li", 6, 1800));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.familyEntryList.add(new FamilyInfoEntry("Liu", 5, 1500));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.familyEntryList.add(new FamilyInfoEntry("Wang", 4, 1300));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.sortedValues = this.familyEntryList.toArray();</DIV>
<DIV><FONT color=#ff0000>&nbsp;//向framework注册一个类型为FamilyInfoDatabase的服务<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context.registerService(FamilyInfoDatabase.class.getName(),this,null);</FONT></DIV>
<DIV><FONT color=#0000ff>&nbsp;</FONT><FONT color=#ff0000>//向framework注册三个服务，每个服务的类型既为FamilyInfoColumn，也是SortingFamilyInfoCriteria<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String[] clazzes = new String[] {FamilyInfoColumn.class.getName(),SortingFamilyInfoCriteria.class.getName()};<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context.registerService(clazzes,new FamilyNameColumn(),null);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context.registerService(clazzes,new FamilyPopulationColumn(),null);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context.registerService(clazzes,new FamilyIncomeColumn(),null);<BR></FONT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR><FONT color=#0000ff>&nbsp;//向framework查找所有注册类型为FamilyInfoColumn的服务<BR>&nbsp;//先获得服务的引用<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ServiceReference[] columnRefs = context.getServiceReferences(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FamilyInfoColumn.class.getName(), null);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FamilyInfoColumn column = null;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; columnRefs.length; i++) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(i + ":" + ((String[])(columnRefs[i].getProperty(Constants.OBJECTCLASS)))[0]);<BR>&nbsp;&nbsp;&nbsp;&nbsp; //通过引用获得具体的服务对象，每一个对象都将转化成gui中table的一列<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; column = (FamilyInfoColumn) context.getService(columnRefs[i]);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (column != null) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.columns.add(column);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("null service object.");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</FONT></DIV>
<DIV><BR><FONT color=#800080>&nbsp;//注册服务侦听器，该侦听器专门侦听FamilyInfoColumn服务对象的动态（主要是增加和删除）<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context.addServiceListener(this，"(" + Constants.OBJECTCLASS + "="<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + FamilyInfoColumn.class.getName() + ")");<BR></FONT>&nbsp;&nbsp;&nbsp; }</DIV>
<DIV>&nbsp;&nbsp;&nbsp; public void stop(BundleContext context) throws Exception {</DIV>
<DIV>&nbsp;&nbsp;&nbsp; }</DIV>
<DIV><FONT color=#800080>&nbsp;&nbsp;&nbsp; public void serviceChanged(ServiceEvent event) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (event.getType()) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case ServiceEvent.MODIFIED:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case ServiceEvent.REGISTERED://表明有新的列产生了。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ServiceReference ref = event.getServiceReference();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object service = this.context.getService(ref);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.columns.add(service);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.fireTableStructureChanged();//通知gui，表结构发生变化<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case ServiceEvent.UNREGISTERING://表明有些列将被删除<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ref = event.getServiceReference();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; service = this.context.getService(ref);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.columns.remove(service);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.fireTableStructureChanged();//通知gui，表结构发生变化<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;</FONT></DIV>
<DIV><FONT color=#800080>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }</FONT></DIV>
<DIV><BR><FONT color=#ff0000>&nbsp;&nbsp;&nbsp; //这个类定义一个“Family Name”这个列，以及如何按这个列的值进行排序<BR>&nbsp;&nbsp;&nbsp; class FamilyNameColumn implements FamilyInfoColumn,SortingFamilyInfoCriteria {<BR></FONT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final String COLUMNNAME = "Family Name";<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public Object getColumnValue(FamilyInfoEntry entry) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return entry.getFamilyName();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public String getColumnName() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FamilyNameColumn.COLUMNNAME;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public String getSortFieldString() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FamilyNameColumn.COLUMNNAME;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int compare(Object obj1, Object obj2) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (obj1 == obj2) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FamilyInfoEntry en1 = (FamilyInfoEntry)obj1;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FamilyInfoEntry en2 = (FamilyInfoEntry)obj2;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return en1.getFamilyName().compareTo(en2.getFamilyName());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; }</DIV>
<DIV><FONT color=#ff0000>&nbsp;&nbsp;&nbsp; //这个类定义一个“Family Population”这个列，以及如何按这个列的值进行排序<BR>&nbsp;&nbsp;&nbsp; class FamilyPopulationColumn implements FamilyInfoColumn, SortingFamilyInfoCriteria {<BR></FONT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final String COLUMNNAME = "Family Population";</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public Object getColumnValue(FamilyInfoEntry entry) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new Integer(entry.getPopulation());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public String getColumnName() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FamilyPopulationColumn.COLUMNNAME;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public String getSortFieldString() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FamilyPopulationColumn.COLUMNNAME;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int compare(Object obj1, Object obj2) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (obj1 == obj2) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FamilyInfoEntry en1 = (FamilyInfoEntry)obj1;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FamilyInfoEntry en2 = (FamilyInfoEntry)obj2;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return en1.getPopulation() - en2.getPopulation();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; <BR><FONT color=#ff0000>&nbsp;&nbsp;&nbsp; //这个类定义一个“Family Income”这个列，以及如何按这个列的值进行排序<BR>&nbsp;&nbsp;&nbsp; class FamilyIncomeColumn implements FamilyInfoColumn, SortingFamilyInfoCriteria {<BR></FONT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final String COLUMNNAME = "Family Income";</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public Object getColumnValue(FamilyInfoEntry entry) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new Integer(entry.getIncomePerYear());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public String getColumnName() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FamilyIncomeColumn.COLUMNNAME;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public String getSortFieldString() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FamilyIncomeColumn.COLUMNNAME;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int compare(Object obj1, Object obj2) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (obj1 == obj2) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FamilyInfoEntry en1 = (FamilyInfoEntry)obj1;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FamilyInfoEntry en2 = (FamilyInfoEntry)obj2;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return en1.getIncomePerYear() - en2.getIncomePerYear();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; }<BR>}</DIV>
<DIV>&nbsp;</DIV>
<DIV>与（五）相比，最大的不同就是表结构的“列”是通过查找所有类型为FamilyInfoColumn的服务对象而组成的。而通过framework提供的服务侦听机制（即实现ServiceListener接口并注册到framework中），bundle能够获得该类服务对象的动态事件通知，如果该事件是新服务注册，则添加一个显示列，如果是服务被注销，则删除对应的显示列。</DIV>
<DIV>&nbsp;</DIV>
<DIV>下面是bundle的manifest文件<BR>Manifest-Version: 1.0<BR>Bundle-SymbolicName: com.bajie.test.family.model<BR>Bundle-Name: family model<BR>Bundle-Version: 1.0<BR>Bundle-Vendor: LiMing<BR>Bundle-Activator: com.bajie.test.family.model.impl.FamilyDatabase<BR><FONT color=#0000ff>Import-Package: org.osgi.framework;version=1.3,com.bajie.test.family.model<BR>Export-Package: com.bajie.test.family.model;version=1.0<BR></FONT></DIV>
<DIV>从中我们看到com.bajie.test.family.model这个package被export出来，这样其他bundle就能够import这个package，并根据FamilyInfoEntry所提供的基本内容提供一些额外的处理结果，从而产生新列(FamilyInfoColumn)以及排序方法(SortingFamilyInfoCriteria)，比如家庭人均年收入。</DIV>
<DIV><BR>下面来看看gui bundle，它只包含一个package</DIV>
<DIV>package com.bajie.test.family.gui;</DIV>
<DIV>import java.awt.BorderLayout;<BR>import java.awt.Dimension;<BR>import java.awt.GridLayout;<BR>import java.awt.event.ActionEvent;<BR>import java.awt.event.ActionListener;<BR>import java.awt.event.ItemEvent;<BR>import java.awt.event.ItemListener;<BR>import java.util.Hashtable;</DIV>
<DIV>import javax.swing.JButton;<BR>import javax.swing.JComboBox;<BR>import javax.swing.JFrame;<BR>import javax.swing.JLabel;<BR>import javax.swing.JPanel;<BR>import javax.swing.JScrollPane;<BR>import javax.swing.JTable;</DIV>
<DIV>import org.osgi.framework.BundleActivator;<BR>import org.osgi.framework.BundleContext;<BR>import org.osgi.framework.Constants;<BR>import org.osgi.framework.ServiceEvent;<BR>import org.osgi.framework.ServiceListener;<BR>import org.osgi.framework.ServiceReference;</DIV>
<DIV>import com.bajie.test.family.model.FamilyInfoDatabase;<BR>import com.bajie.test.family.model.SortingFamilyInfoCriteria;</DIV>
<DIV>public class FamilyInfoGui implements BundleActivator, ActionListener,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ItemListener, ServiceListener {<BR>&nbsp;&nbsp;&nbsp; private JFrame mainFrame;</DIV>
<DIV>&nbsp;&nbsp;&nbsp; private JPanel contentPanel;</DIV>
<DIV>&nbsp;&nbsp;&nbsp; private JTable familiesTable;</DIV>
<DIV>&nbsp;&nbsp;&nbsp; private JScrollPane familiesTableScrollPane;</DIV>
<DIV>&nbsp;&nbsp;&nbsp; private JPanel sortedByPanel = new JPanel(new GridLayout(1, 2));</DIV>
<DIV>&nbsp;&nbsp;&nbsp; private JLabel sortedByLabel = new JLabel("Sorted By: ");</DIV>
<DIV>&nbsp;&nbsp;&nbsp; private JComboBox sortedByList = null;</DIV>
<DIV>&nbsp;&nbsp;&nbsp; private JPanel commandPanel = new JPanel(new GridLayout(1, 3));</DIV>
<DIV>&nbsp;&nbsp;&nbsp; private JButton addEntry = new JButton("Add");</DIV>
<DIV>&nbsp;&nbsp;&nbsp; private JButton deleteEntry = new JButton("Delete");</DIV>
<DIV>&nbsp;&nbsp;&nbsp; private JButton updateEntry = new JButton("Update");</DIV>
<DIV>&nbsp;&nbsp;&nbsp; private Hashtable sortingFields = new Hashtable();</DIV>
<DIV>&nbsp;&nbsp;&nbsp; private BundleContext context;</DIV>
<DIV>&nbsp;&nbsp;&nbsp; FamilyInfoDatabase database = null;</DIV>
<DIV>&nbsp;&nbsp;&nbsp; public void start(BundleContext context) throws Exception {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.context = context;<BR><FONT color=#0000ff>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //查找所有注册类型为FamilyInfoDatabase的服务对象。在我们这个例子，它是由上面给出的model bundle注册的<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ServiceReference databaseServiceRef = context<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .getServiceReference(FamilyInfoDatabase.class.getName());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (databaseServiceRef == null) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("No database service is registered.");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</FONT></DIV>
<DIV><FONT color=#0000ff>&nbsp;//这个服务对象将成为JTable的数据model<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.database = (FamilyInfoDatabase) context<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .getService(databaseServiceRef);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (this.database == null) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Can not get database object");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</FONT></DIV>
<DIV><FONT color=#0000ff>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //查找所有注册类型为SortingFamilyInfoCriteria的服务对象。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ServiceReference[] sortingCriteria = context.getServiceReferences(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SortingFamilyInfoCriteria.class.getName(), null);</FONT></DIV>
<DIV><FONT color=#0000ff>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sortedByList = new JComboBox();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SortingFamilyInfoCriteria criterion = null;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (sortingCriteria != null) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; sortingCriteria.length; i++) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; criterion = (SortingFamilyInfoCriteria) context<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .getService(sortingCriteria[i]);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (criterion != null) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //每个服务对象将对应一种排序方法，并加入到下拉列表中<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sortedByList.addItem(criterion.getSortFieldString());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.sortingFields.put(criterion.getSortFieldString(),<BR>&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;&nbsp; criterion);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</FONT></DIV>
<DIV><FONT color=#800080>&nbsp;//注册服务侦听器，该侦听器专门侦听SortingFamilyInfoCriteria服务对象的动态（主要是增加和删除）<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context.addServiceListener(this, "(" + Constants.OBJECTCLASS + "="<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + SortingFamilyInfoCriteria.class.getName() + ")");</FONT></DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sortedByList.addItemListener(FamilyInfoGui.this);</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //construct gui<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Runnable r = new Runnable() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; contentPanel = new JPanel();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; familiesTableScrollPane = new JScrollPane();<BR>&nbsp;&nbsp;//获得的FamilyInfoDatabase对象成为gui中JTable的model<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; familiesTable = new JTable(database);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; familiesTableScrollPane.setViewportView(familiesTable);</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sortedByPanel.add(sortedByLabel);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sortedByPanel.add(sortedByList);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; commandPanel.add(addEntry);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; commandPanel.add(deleteEntry);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; commandPanel.add(updateEntry);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; contentPanel.add(sortedByPanel, BorderLayout.NORTH);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; contentPanel.add(familiesTableScrollPane, BorderLayout.CENTER);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; contentPanel.add(commandPanel, BorderLayout.SOUTH);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mainFrame = new JFrame();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mainFrame.setContentPane(contentPanel);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mainFrame.setSize(new Dimension(500, 600));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mainFrame.show();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread t = new Thread(r);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t.start();<BR>&nbsp;&nbsp;&nbsp; }</DIV>
<DIV>&nbsp;&nbsp;&nbsp; public void stop(BundleContext context) throws Exception {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (this.mainFrame != null)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.mainFrame.dispose();<BR>&nbsp;&nbsp;&nbsp; }</DIV>
<DIV>&nbsp;&nbsp;&nbsp; public void actionPerformed(ActionEvent event) {<BR>&nbsp;&nbsp;&nbsp; }</DIV>
<DIV>&nbsp;&nbsp;&nbsp; public void itemStateChanged(ItemEvent event) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (event.getSource() == this.sortedByList) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SortingFamilyInfoCriteria criterion = (SortingFamilyInfoCriteria) this.sortingFields<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .get(event.getItem());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (criterion == null)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.database.sort(criterion);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.familiesTable.repaint();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }</DIV>
<DIV><FONT color=#800080>&nbsp;&nbsp;&nbsp; public void serviceChanged(ServiceEvent event) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (event.getType()) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case ServiceEvent.MODIFIED:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case ServiceEvent.REGISTERED://有新的排序方法注册到framework当中<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ServiceReference ref = event.getServiceReference();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SortingFamilyInfoCriteria criterion = (SortingFamilyInfoCriteria) this.context<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .getService(ref);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (criterion != null) {<BR>&nbsp;&nbsp;//把新的排序方法加入到下拉列表中<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sortedByList.addItem(criterion.getSortFieldString());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.sortingFields.put(criterion.getSortFieldString(),<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; criterion);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case ServiceEvent.UNREGISTERING://一个现有的排序方法将被从framework被取消<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ref = event.getServiceReference();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; criterion = (SortingFamilyInfoCriteria) this.context<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .getService(ref);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (criterion != null) {<BR>&nbsp;&nbsp;//把该排序方法从下拉列表中删除<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sortedByList.removeItem(criterion.getSortFieldString());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.sortingFields.remove(criterion);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;</FONT></DIV>
<DIV><FONT color=#800080>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }</FONT></DIV>
<DIV>}</DIV>
<DIV>&nbsp;</DIV>
<DIV>与（五）相比不同的地方是，这个gui的table model以及排序的方法，都是通过查询service对象获得。</DIV>
<DIV>&nbsp;</DIV>
<DIV>manifest文件如下：<BR>Manifest-Version: 1.0<BR>Bundle-SymbolicName: com.bajie.test.family.gui<BR>Bundle-Name: family gui<BR>Bundle-Version: 1.0<BR>Bundle-Vendor: LiMing<BR>Bundle-Activator: com.bajie.test.family.gui.FamilyInfoGui<BR><FONT color=#0000ff>Import-Package: org.osgi.framework;version=1.3,com.bajie.test.family.model</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV>然后我们生成bundle的jar文件。分别为familymodel.jar和familygui.jar，之后我们用“in”命令把两个bundle装入framework。<BR>接着我们先启动model bundle，然后再启动gui bundle，我们会看到JTable中有3列，而排序方法列表中也有3个选项，完全和程序的逻辑符合。</DIV>
<DIV>&nbsp;</DIV>
<DIV>接下来，我们假设客户需要添加显示每个家庭的人均年收入并按其排列纪录。要满足这个需求，我们可以参考在（五）中做法，就是在model bundle里面再添加一个同时实现了FamilyInfoColumn和SortingFamilyInfoCriteria的类，并在bundle的启动中作为服务注册到framework中？不过这样就得更新model bundle然后调用rfr命令来刷新。为什么不再装一个补丁bundle，在这个bundle中包含了同时实现FamilyInfoColumn和SortingFamilyInfoCriteria的类，并在这个新bunle启动时注册产生该类的新对象作为服务注册到framework中，这样gui和model bundle都能侦听到该新服务的到来(他们都实现了服务侦听接口ServiceListener)，gui上马上就能有所体现。</DIV>
<DIV><BR>这个新bundle的代码如下：<BR>package com.bajie.test.family.model.impladd;</DIV>
<DIV>import org.osgi.framework.BundleActivator;<BR>import org.osgi.framework.BundleContext;</DIV>
<DIV>import com.bajie.test.family.model.FamilyInfoColumn;<BR>import com.bajie.test.family.model.FamilyInfoEntry;<BR>import com.bajie.test.family.model.SortingFamilyInfoCriteria;</DIV>
<DIV>public class FamilyIncomePerPerson implements BundleActivator {</DIV>
<DIV>&nbsp;&nbsp;&nbsp; public void start(BundleContext context) throws Exception {<BR><FONT color=#ff0000>&nbsp;//注册一个新的服务，服务的类型既为FamilyInfoColumn，也是SortingFamilyInfoCriteria<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String[] clazzes = new String[] {FamilyInfoColumn.class.getName(),SortingFamilyInfoCriteria.class.getName()};<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context.registerService(clazzes,new FamilyIncomePerPersonColumn(),null);<BR></FONT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; }</DIV>
<DIV>&nbsp;&nbsp;&nbsp; public void stop(BundleContext context) throws Exception {</DIV>
<DIV>&nbsp;&nbsp;&nbsp; }</DIV>
<DIV><FONT color=#ff0000>&nbsp;&nbsp;&nbsp; //这个类实现了“Income Per Person”这个列以及按该列排序的方法。<BR>&nbsp;&nbsp;&nbsp; class FamilyIncomePerPersonColumn implements FamilyInfoColumn,SortingFamilyInfoCriteria {<BR></FONT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final String COLUMNNAME = "Income Per Person";<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public Object getColumnValue(FamilyInfoEntry entry) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new Integer(entry.getIncomePerYear()/entry.getPopulation());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public String getColumnName() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FamilyIncomePerPersonColumn.COLUMNNAME;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public String getSortFieldString() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FamilyIncomePerPersonColumn.COLUMNNAME;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</DIV>
<DIV>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int compare(Object obj1, Object obj2) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (obj1 == obj2) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FamilyInfoEntry en1 = (FamilyInfoEntry)obj1;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FamilyInfoEntry en2 = (FamilyInfoEntry)obj2;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return en1.getIncomePerYear()/en1.getPopulation() - en2.getIncomePerYear()/en2.getPopulation();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; }<BR>}</DIV>
<DIV>&nbsp;</DIV>
<DIV>manifest文件如下：<BR>Manifest-Version: 1.0<BR>Bundle-SymbolicName: com.bajie.test.family.modeladd<BR>Bundle-Name: family model add<BR>Bundle-Version: 1.0<BR>Bundle-Vendor: LiMing<BR>Bundle-Activator: com.bajie.test.family.model.impladd.FamilyIncomePerPerson<BR>Import-Package: org.osgi.framework;version=1.3,com.bajie.test.family.model</DIV>
<DIV>&nbsp;</DIV>
<DIV>打包安装到framework后，启动该bundle，我们就会在gui上看到新的列已经被添加，而且排序列表中增加了一个新的排序选项。<BR>这个结果，完全符合需求的意图。</DIV>
<DIV>如果我们用stp命令停止这个bundle，我们在gui上就会发现，新列消失，而且排序列表中对应选项也没有了。这就是service带来的动态效果。不过，如果我们的model发生了一些实质的变化，比如FamilyInfoEntry需要添加一个“地址”列，那么model bundle就要更新，进而gui bundle以及使用到这个类型的bundle都需要通过rfr命令刷新。</DIV>
<DIV>&nbsp;</DIV>
<DIV>好了，对扶贫助手的分析就此打住，我们总结一下，通过程序可以看到注册服务一点都不复杂。最简单的情况我们只需要提供一个java类型名称，以及实现这个类型的一个java对象就可以了，<BR>不需要提供复杂的类型描述，比如xml描述文件。而使用服务的bundle通过类型名称就轻而易举的查找到相关的服务对象。</DIV>
<DIV>&nbsp;</DIV>
<DIV>到此，osig介绍系列就要结束了，只希望这个系列能够把你引入到osgi的门口，其后面的精彩世界就看你的兴趣了。<BR>就我个人的关注和理解，今年是osgi很重要的一年。JSR249今年应该投票，如果osgi入选，那么osgi将成为高端手机中java体系结构的重要组成部分。<BR>在汽车领域，siemensVDO已经推出了基于osgi的解决方案，听说已经配备在BMW serials 5里面了。应该还会有更多的应用......</DIV>
<DIV>&nbsp;</DIV>
<DIV>如果你是osgi的粉丝，欢迎你来信<A href="mailto:jerrylee.li@gmail.com"><FONT color=#004377>jerrylee.li@gmail.com</FONT></A>拍砖交流。</DIV><img src ="http://www.blogjava.net/Ferrari4000/aggbug/30626.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Ferrari4000/" target="_blank">勤劳的蜜蜂</a> 2006-02-14 16:08 <a href="http://www.blogjava.net/Ferrari4000/archive/2006/02/14/30626.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OSGi介绍（五）两个bundle</title><link>http://www.blogjava.net/Ferrari4000/archive/2006/02/14/30625.html</link><dc:creator>勤劳的蜜蜂</dc:creator><author>勤劳的蜜蜂</author><pubDate>Tue, 14 Feb 2006 08:02:00 GMT</pubDate><guid>http://www.blogjava.net/Ferrari4000/archive/2006/02/14/30625.html</guid><wfw:comment>http://www.blogjava.net/Ferrari4000/comments/30625.html</wfw:comment><comments>http://www.blogjava.net/Ferrari4000/archive/2006/02/14/30625.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/Ferrari4000/comments/commentRss/30625.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Ferrari4000/services/trackbacks/30625.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: （四）中提到的直接型改造法实际上和一个传统的java应用程序没有区别。因此客户的需求发生变化，通常是牵一发而动全身。那么我们现在就看看如果在osgi framework中，用多个bundle来实现的效果吧。我的想法是用两个bundle来配合实现“扶贫助手”的功能。一个bundle专门负责录入和显示纪录，一个bundle专门负责纪录的数据结构和对数据的处理，用时下时髦的说法就是使用了mvc，只是...&nbsp;&nbsp;<a href='http://www.blogjava.net/Ferrari4000/archive/2006/02/14/30625.html'>阅读全文</a><img src ="http://www.blogjava.net/Ferrari4000/aggbug/30625.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Ferrari4000/" target="_blank">勤劳的蜜蜂</a> 2006-02-14 16:02 <a href="http://www.blogjava.net/Ferrari4000/archive/2006/02/14/30625.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OSGi介绍（四）第一个bundle</title><link>http://www.blogjava.net/Ferrari4000/archive/2006/02/14/30622.html</link><dc:creator>勤劳的蜜蜂</dc:creator><author>勤劳的蜜蜂</author><pubDate>Tue, 14 Feb 2006 07:46:00 GMT</pubDate><guid>http://www.blogjava.net/Ferrari4000/archive/2006/02/14/30622.html</guid><wfw:comment>http://www.blogjava.net/Ferrari4000/comments/30622.html</wfw:comment><comments>http://www.blogjava.net/Ferrari4000/archive/2006/02/14/30622.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/Ferrari4000/comments/commentRss/30622.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Ferrari4000/services/trackbacks/30622.html</trackback:ping><description><![CDATA[先给出“扶贫助手”的第一种改造，我称之为“直接型”，请看：<BR><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><SPAN style="COLOR: #0000ff">package</SPAN><SPAN style="COLOR: #000000">&nbsp;aa.bb.cc;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">需要import&nbsp;osgi的核心package</SPAN><SPAN style="COLOR: #008000"><BR><IMG 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;<BR><IMG 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;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">实现了BundleActivator</SPAN><SPAN style="COLOR: #008000"><BR><IMG id=Codehighlighter1_200_2257_Open_Image onclick="this.style.display='none'; Codehighlighter1_200_2257_Open_Text.style.display='none'; Codehighlighter1_200_2257_Closed_Image.style.display='inline'; Codehighlighter1_200_2257_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_200_2257_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_200_2257_Closed_Text.style.display='none'; Codehighlighter1_200_2257_Open_Image.style.display='inline'; Codehighlighter1_200_2257_Open_Text.style.display='inline';" 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;FamilyInfo&nbsp;</SPAN><SPAN style="COLOR: #0000ff">implements</SPAN><SPAN style="COLOR: #000000">&nbsp;BundleActivator&nbsp;</SPAN><SPAN id=Codehighlighter1_200_2257_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"></SPAN><SPAN id=Codehighlighter1_200_2257_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;String&nbsp;familyName;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;population;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;incomePerYear;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;<IMG src="http://www.blogjava.net/images/dot.gif"><IMG src="http://www.blogjava.net/images/dot.gif">省略了getter和setter方法&nbsp;<BR><IMG id=Codehighlighter1_336_454_Open_Image onclick="this.style.display='none'; Codehighlighter1_336_454_Open_Text.style.display='none'; Codehighlighter1_336_454_Closed_Image.style.display='inline'; Codehighlighter1_336_454_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_336_454_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_336_454_Closed_Text.style.display='none'; Codehighlighter1_336_454_Open_Image.style.display='inline'; Codehighlighter1_336_454_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;String&nbsp;toString()&nbsp;</SPAN><SPAN id=Codehighlighter1_336_454_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"></SPAN><SPAN id=Codehighlighter1_336_454_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">Family:&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">.familyName&nbsp;</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;population:&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">.population&nbsp;</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;income:&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">.incomePerYear;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;<BR><IMG id=Codehighlighter1_490_545_Open_Image onclick="this.style.display='none'; Codehighlighter1_490_545_Open_Text.style.display='none'; Codehighlighter1_490_545_Closed_Image.style.display='inline'; Codehighlighter1_490_545_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_490_545_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_490_545_Closed_Text.style.display='none'; Codehighlighter1_490_545_Open_Image.style.display='inline'; Codehighlighter1_490_545_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;getIncomePerMember()</SPAN><SPAN id=Codehighlighter1_490_545_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"></SPAN><SPAN id=Codehighlighter1_490_545_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">)(</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">.incomePerYear</SPAN><SPAN style="COLOR: #000000">/</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">.population);<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG id=Codehighlighter1_609_914_Open_Image onclick="this.style.display='none'; Codehighlighter1_609_914_Open_Text.style.display='none'; Codehighlighter1_609_914_Closed_Image.style.display='inline'; Codehighlighter1_609_914_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_609_914_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_609_914_Closed_Text.style.display='none'; Codehighlighter1_609_914_Open_Image.style.display='inline'; Codehighlighter1_609_914_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">static</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;sortByIncomePerYear(FamilyInfo[]&nbsp;families)</SPAN><SPAN id=Codehighlighter1_609_914_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"></SPAN><SPAN id=Codehighlighter1_609_914_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;FamilyInfo&nbsp;temp&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">null</SPAN><SPAN style="COLOR: #000000">;<BR><IMG id=Codehighlighter1_683_908_Open_Image onclick="this.style.display='none'; Codehighlighter1_683_908_Open_Text.style.display='none'; Codehighlighter1_683_908_Closed_Image.style.display='inline'; Codehighlighter1_683_908_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_683_908_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_683_908_Closed_Text.style.display='none'; Codehighlighter1_683_908_Open_Image.style.display='inline'; Codehighlighter1_683_908_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;families.length&nbsp;</SPAN><SPAN style="COLOR: #000000">-</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">;&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">++</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN id=Codehighlighter1_683_908_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"></SPAN><SPAN id=Codehighlighter1_683_908_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG id=Codehighlighter1_733_904_Open_Image onclick="this.style.display='none'; Codehighlighter1_733_904_Open_Text.style.display='none'; Codehighlighter1_733_904_Closed_Image.style.display='inline'; Codehighlighter1_733_904_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_733_904_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_733_904_Closed_Text.style.display='none'; Codehighlighter1_733_904_Open_Image.style.display='inline'; Codehighlighter1_733_904_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;j&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">;&nbsp;j&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;families.length;&nbsp;j&nbsp;</SPAN><SPAN style="COLOR: #000000">++</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN id=Codehighlighter1_733_904_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"></SPAN><SPAN id=Codehighlighter1_733_904_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<BR><IMG id=Codehighlighter1_811_899_Open_Image onclick="this.style.display='none'; Codehighlighter1_811_899_Open_Text.style.display='none'; Codehighlighter1_811_899_Closed_Image.style.display='inline'; Codehighlighter1_811_899_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_811_899_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_811_899_Closed_Text.style.display='none'; Codehighlighter1_811_899_Open_Image.style.display='inline'; Codehighlighter1_811_899_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">(families[i].getIncomePerYear()&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;families[j].getIncomePerYear())</SPAN><SPAN id=Codehighlighter1_811_899_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"></SPAN><SPAN id=Codehighlighter1_811_899_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;families[i];<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;families[i]&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;families[j];<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;families[j]&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;temp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG id=Codehighlighter1_980_1292_Open_Image onclick="this.style.display='none'; Codehighlighter1_980_1292_Open_Text.style.display='none'; Codehighlighter1_980_1292_Closed_Image.style.display='inline'; Codehighlighter1_980_1292_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_980_1292_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_980_1292_Closed_Text.style.display='none'; Codehighlighter1_980_1292_Open_Image.style.display='inline'; Codehighlighter1_980_1292_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">static</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;sortByIncomePerMember(FamilyInfo[]&nbsp;families)</SPAN><SPAN id=Codehighlighter1_980_1292_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"></SPAN><SPAN id=Codehighlighter1_980_1292_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;FamilyInfo&nbsp;temp&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">null</SPAN><SPAN style="COLOR: #000000">;<BR><IMG id=Codehighlighter1_1054_1283_Open_Image onclick="this.style.display='none'; Codehighlighter1_1054_1283_Open_Text.style.display='none'; Codehighlighter1_1054_1283_Closed_Image.style.display='inline'; Codehighlighter1_1054_1283_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_1054_1283_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1054_1283_Closed_Text.style.display='none'; Codehighlighter1_1054_1283_Open_Image.style.display='inline'; Codehighlighter1_1054_1283_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;families.length&nbsp;</SPAN><SPAN style="COLOR: #000000">-</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">;&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">++</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN id=Codehighlighter1_1054_1283_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"></SPAN><SPAN id=Codehighlighter1_1054_1283_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG id=Codehighlighter1_1104_1279_Open_Image onclick="this.style.display='none'; Codehighlighter1_1104_1279_Open_Text.style.display='none'; Codehighlighter1_1104_1279_Closed_Image.style.display='inline'; Codehighlighter1_1104_1279_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_1104_1279_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1104_1279_Closed_Text.style.display='none'; Codehighlighter1_1104_1279_Open_Image.style.display='inline'; Codehighlighter1_1104_1279_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;j&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">;&nbsp;j&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;families.length;&nbsp;j&nbsp;</SPAN><SPAN style="COLOR: #000000">++</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN id=Codehighlighter1_1104_1279_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"></SPAN><SPAN id=Codehighlighter1_1104_1279_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<BR><IMG id=Codehighlighter1_1186_1274_Open_Image onclick="this.style.display='none'; Codehighlighter1_1186_1274_Open_Text.style.display='none'; Codehighlighter1_1186_1274_Closed_Image.style.display='inline'; Codehighlighter1_1186_1274_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_1186_1274_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1186_1274_Closed_Text.style.display='none'; Codehighlighter1_1186_1274_Open_Image.style.display='inline'; Codehighlighter1_1186_1274_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">(families[i].getIncomePerMember()&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;families[j].getIncomePerMember())</SPAN><SPAN id=Codehighlighter1_1186_1274_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"></SPAN><SPAN id=Codehighlighter1_1186_1274_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;families[i];<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;families[i]&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;families[j];<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;families[j]&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;temp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">在framework每次启动该bundle的时候该方法会被framework调用执行。</SPAN><SPAN style="COLOR: #008000"><BR><IMG id=Codehighlighter1_1400_2151_Open_Image onclick="this.style.display='none'; Codehighlighter1_1400_2151_Open_Text.style.display='none'; Codehighlighter1_1400_2151_Closed_Image.style.display='inline'; Codehighlighter1_1400_2151_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_1400_2151_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1400_2151_Closed_Text.style.display='none'; Codehighlighter1_1400_2151_Open_Image.style.display='inline'; Codehighlighter1_1400_2151_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top></SPAN><SPAN style="COLOR: #000000">&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_1400_2151_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"></SPAN><SPAN id=Codehighlighter1_1400_2151_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;FamilyInfo[]&nbsp;families&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;FamilyInfo[</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">];<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;families[</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">]&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;FamilyInfo();<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;families[</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">].setFamilyName(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">Zhang</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;families[</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">].setPopulation(</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">);<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;families[</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">].setIncomePerYear(</SPAN><SPAN style="COLOR: #000000">1200</SPAN><SPAN style="COLOR: #000000">);<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;families[</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">]&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;FamilyInfo();<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;families[</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">].setFamilyName(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">Li</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;families[</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">].setPopulation(</SPAN><SPAN style="COLOR: #000000">6</SPAN><SPAN style="COLOR: #000000">);<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;families[</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">].setIncomePerYear(</SPAN><SPAN style="COLOR: #000000">1800</SPAN><SPAN style="COLOR: #000000">);<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;families[</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">]&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;FamilyInfo();<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;families[</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">].setFamilyName(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">Liu</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;families[</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">].setPopulation(</SPAN><SPAN style="COLOR: #000000">4</SPAN><SPAN style="COLOR: #000000">);<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;families[</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">].setIncomePerYear(</SPAN><SPAN style="COLOR: #000000">1500</SPAN><SPAN style="COLOR: #000000">);<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;FamilyInfo.sortByIncomePerYear(families);<BR><IMG id=Codehighlighter1_1955_2006_Open_Image onclick="this.style.display='none'; Codehighlighter1_1955_2006_Open_Text.style.display='none'; Codehighlighter1_1955_2006_Closed_Image.style.display='inline'; Codehighlighter1_1955_2006_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_1955_2006_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1955_2006_Closed_Text.style.display='none'; Codehighlighter1_1955_2006_Open_Image.style.display='inline'; Codehighlighter1_1955_2006_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;families.length;&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">++</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN id=Codehighlighter1_1955_2006_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"></SPAN><SPAN id=Codehighlighter1_1955_2006_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;System.out.println(families[i].toString());<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;FamilyInfo.sortByIncomePerMember(families);<BR><IMG id=Codehighlighter1_2097_2148_Open_Image onclick="this.style.display='none'; Codehighlighter1_2097_2148_Open_Text.style.display='none'; Codehighlighter1_2097_2148_Closed_Image.style.display='inline'; Codehighlighter1_2097_2148_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_2097_2148_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_2097_2148_Closed_Text.style.display='none'; Codehighlighter1_2097_2148_Open_Image.style.display='inline'; Codehighlighter1_2097_2148_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;families.length;&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">++</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN id=Codehighlighter1_2097_2148_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"></SPAN><SPAN id=Codehighlighter1_2097_2148_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;System.out.println(families[i].toString());<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">在framework停止该bundle时，该方法将被framework调用</SPAN><SPAN style="COLOR: #008000"><BR><IMG id=Codehighlighter1_2252_2255_Open_Image onclick="this.style.display='none'; Codehighlighter1_2252_2255_Open_Text.style.display='none'; Codehighlighter1_2252_2255_Closed_Image.style.display='inline'; Codehighlighter1_2252_2255_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_2252_2255_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_2252_2255_Closed_Text.style.display='none'; Codehighlighter1_2252_2255_Open_Image.style.display='inline'; Codehighlighter1_2252_2255_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top></SPAN><SPAN style="COLOR: #000000">&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_2252_2255_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"></SPAN><SPAN id=Codehighlighter1_2252_2255_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN></DIV><BR>看到代码的区别了吗？我在不同之处都标注了注释。其实，从说白了，就是实现了org.osgi.framework.BundleActivator这个接口。
<DIV>当然，细心的话，你会发现这个bundle没有public static void main(String[] args)方法了。那么它怎么被启动呢？这个就是bundle的奥秘所在。不过，如果你了解java的class loading机制以及reflection技术，你立马会明白这个bundle的运行机制。这两项技术广泛应用于j2ee（对吧？我得承认，j2ee的经验不多，呵呵）以及java的plugin机制。<BR>简单说来，java.lang.Class这个类有一个方法:<BR>public Object newInstance()throws InstantiationException,IllegalAccessException<BR>针对上面的“扶贫助手”bundle而言，framework只要通过ClassLoader找到aa.bb.cc.FamilyInfo.class并加载后，就可以通过newInstance()方法创建一个BundleActivator的实例，然后调用public void start(BundleContext context)方法，就完成了启动bundle的动作了。之后，调用public<BR>void stop(BundleContext context)方法来停止bundle</DIV>
<DIV>如果你接着问，framework怎么知道这个bundle里面的BundleActivator是哪个类呢？嗯，问到点子上了。这就涉及到下面我们要讲的bundle的部署了。在上一篇给出的bundle定义中指出，Jar文件是bundle的唯一格式，也就是说，我们要运行bundle，必须把代码打成jar文件。而jar文件可以带有manifest文件，这个文件对bundle是不可缺少的。OSGi规范里面，通过定义一系列适用于bundle的manifest关键字(bundle manifest header)来扩展manifest文件。<BR>比如，开发人员在manifest中添加下面一行：<BR>Bundle-Activator: aa.bb.cc.FamilyInfo<BR>这样，在bundle被部署到framework后，framework就可以通过读取manifest的关键字来获得BundleActivator的具体实现类名，并通过reflection机制产生BundleActivator的实例。</DIV>
<DIV>这里就给出扶贫助手的manifest的一个例子：<BR><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><SPAN style="COLOR: #000000">Manifest-Version:&nbsp;</SPAN><SPAN style="COLOR: #000000">1.0</SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>Bundle-SymbolicName:&nbsp;aa.bb.cc.family&nbsp;//osgi&nbsp;specification&nbsp;4强制要求的关键字，每个bundle都必须有唯一的symbolic&nbsp;name<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>Bundle-Name:&nbsp;Family&nbsp;Info&nbsp;Manager&nbs