﻿<?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-ultramarine-文章分类-eclipse&amp;Java</title><link>http://www.blogjava.net/ultramarine/category/3378.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 12:34:29 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 12:34:29 GMT</pubDate><ttl>60</ttl><item><title>ZT：Eclipse(3.1) Plugin Framework(基于OSGI的Plugin Architecture) </title><link>http://www.blogjava.net/ultramarine/articles/13827.html</link><dc:creator>ultramarine</dc:creator><author>ultramarine</author><pubDate>Fri, 23 Sep 2005 03:52:00 GMT</pubDate><guid>http://www.blogjava.net/ultramarine/articles/13827.html</guid><wfw:comment>http://www.blogjava.net/ultramarine/comments/13827.html</wfw:comment><comments>http://www.blogjava.net/ultramarine/articles/13827.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ultramarine/comments/commentRss/13827.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ultramarine/services/trackbacks/13827.html</trackback:ping><description><![CDATA[<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><b><span style="font-family: 宋体;">概述</span></b><span lang="EN-US"><br>Eclipse </span><span style="font-family: 宋体;">中最出彩的部分莫过于它的</span><span lang="EN-US">Plugin Framework</span><span style="font-family: 宋体;">，可以说</span><span lang="EN-US">Eclipse</span><span style="font-family: 宋体;">在一定程度上使得</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">机制得以流行，当然，</span><span lang="EN-US">Eclipse</span><span style="font-family: 宋体;">的优势不仅仅在此，但正因为采用了</span><span lang="EN-US"> Plugin</span><span style="font-family: 宋体;">机制，</span><span lang="EN-US">Eclipse</span><span style="font-family: 宋体;">才得以被不断的扩充，越来越强大。一直以来就想分析</span><span lang="EN-US">Eclipse</span><span style="font-family: 宋体;">的</span><span lang="EN-US">Plugin Framework</span><span style="font-family: 宋体;">，由于各种原因一直耽搁，刚好这个周末没什么事，下定决心对其进行了研究和分析，方法很原始，就是对</span><span lang="EN-US">Eclipse</span><span style="font-family: 宋体;">的启动过程进行分</span> 
<span style="font-family: 宋体;">析，基于的是</span><span lang="EN-US">Eclipse 3.1</span><span style="font-family: 宋体;">的版本，分析过程就不在这说了，主要是说说分析出来的心得。</span><span lang="EN-US"><br></span><span style="font-family: 宋体;">架构上来讲</span><span lang="EN-US">Eclipse</span><span style="font-family: 宋体;">基本采用的是</span><span lang="EN-US">Kernel+Core Plugins+Custom Plugins</span><span style="font-family: 宋体;">的结构体系，除了</span><span lang="EN-US">Kernel</span><span style="font-family: 宋体;">部分外均为</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">，所以可称为</span><span lang="EN-US">all are plugins</span><span style="font-family: 宋体;">，凡是</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">的部分都是可被替换的。</span><span lang="EN-US"><o:p></o:p></span></p>

<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><b><span lang="EN-US">OSGI</span></b><span lang="EN-US"><br>Eclipse 3.0</span><span style="font-family: 宋体;">后采用的是</span><span lang="EN-US">OSGI</span><span style="font-family: 宋体;">来作为其</span><span lang="EN-US">Plugin Architecture</span><span style="font-family: 宋体;">实现的依据，鉴于此就得简单提提</span><span lang="EN-US">OSGI</span><span style="font-family: 宋体;">了，主要从</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">的角度来分析</span><span lang="EN-US">OSGI</span><span style="font-family: 宋体;">，</span><span lang="EN-US">OSGI</span><span style="font-family: 宋体;">概念中主要分为了</span><span lang="EN-US">Bundle</span><span style="font-family: 宋体;">和</span><span lang="EN-US"> Service</span><span style="font-family: 宋体;">，可以认为</span><span lang="EN-US">Bundle</span><span style="font-family: 宋体;">是一个模块的管理器，主要是通过</span><span lang="EN-US">BundleActivator</span><span style="font-family: 宋体;">管理模块的生命周期，而</span><span lang="EN-US">Service</span><span style="font-family: 宋体;">则是这个模块</span> 
<span style="font-family: 宋体;">可暴露对外的服务对象，这里体现了</span><span lang="EN-US">OSGI</span><span style="font-family: 宋体;">和传统的</span><span lang="EN-US">Plugin Framework</span><span style="font-family: 宋体;">不同的一个地方，管理和静态结构分开，在</span><span lang="EN-US">OSGI</span><span style="font-family: 宋体;">中通过在</span><span lang="EN-US">manifest.mf</span><span style="font-family: 宋体;">文件中增加一些内容来发布</span><span lang="EN-US">Bundle</span><span style="font-family: 宋体;">，在其中描述了</span><span lang="EN-US"> Bundle</span><span style="font-family: 宋体;">的提供商、版本、唯一</span><span lang="EN-US">ID</span><span style="font-family: 宋体;">、</span><span lang="EN-US">classpath</span><span style="font-family: 宋体;">、暴露对外的包、所依赖的包；每个</span><span lang="EN-US">Bundle</span><span style="font-family: 宋体;">拥有自己的</span><span lang="EN-US">ClassLoader</span><span style="font-family: 宋体;">以及</span><span lang="EN-US"> context</span><span style="font-family: 宋体;">，通过</span><span lang="EN-US">context</span><span style="font-family: 宋体;">可进行服务的注册、卸载等，这些操作都会通过事件机制广播给相应的其他的</span><span lang="EN-US">Bundle</span><span style="font-family: 宋体;">；一般来说都为通过在</span><span lang="EN-US"> Bundle</span><span style="font-family: 宋体;">中编写初始需要注册的服务的方法来完成</span><span lang="EN-US">Bundle</span><span style="font-family: 宋体;">可供外部使用的服务的暴露功能；如需要调用其他</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">提供的服务可通过</span><span lang="EN-US"> context</span><span style="font-family: 宋体;">的</span><span lang="EN-US">getServiceReference</span><span style="font-family: 宋体;">先获取</span><span lang="EN-US">Service</span><span style="font-family: 宋体;">的句柄，再通过</span><span lang="EN-US">context.getService (ServiceReference)</span><span style="font-family: 宋体;">的方法获取</span><span lang="EN-US">Service</span><span style="font-family: 宋体;">的实体。</span><span lang="EN-US"><o:p></o:p></span></p>

<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><b><span lang="EN-US">Eclipse 
Plugin</span></b><b><span style="font-family: 宋体;">定义</span><span lang="EN-US"><br></span></b><span lang="EN-US">Eclipse </span><span style="font-family: 宋体;">中的</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">的概念为包含一系列服务的模块即为一个</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">。既然是遵循</span><span lang="EN-US">OSGI</span><span style="font-family: 宋体;">的，也就意味着</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">通常是由</span><span lang="EN-US">Bundle</span><span style="font-family: 宋体;">和</span><span lang="EN-US">N</span><span style="font-family: 宋体;">多</span><span lang="EN-US"> Service</span><span style="font-family: 宋体;">共同构成的，在此基础上</span><span lang="EN-US">Eclipse</span><span style="font-family: 宋体;">认为</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">之间通常存在两种关系，一种为依赖，一种为扩展，对于依赖可通过</span><span lang="EN-US">OSGI</span><span style="font-family: 宋体;">中元描述信</span> 
<span style="font-family: 宋体;">息里添加需要引用的</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">即可实现，但扩展在</span><span lang="EN-US">OSGI</span><span style="font-family: 宋体;">中是没有定义的，</span><span lang="EN-US">Eclipse</span><span style="font-family: 宋体;">采用了一个</span><span lang="EN-US">Extension Point</span><span style="font-family: 宋体;">的方式来实现</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">的扩展功能。</span><span lang="EN-US"><br></span><span style="font-family: 宋体;">结合</span><span lang="EN-US">OSGI<br>Eclipse</span><span style="font-family: 宋体;">遵循</span><span lang="EN-US">OSGI</span><span style="font-family: 宋体;">对于</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">的</span><span lang="EN-US">ID</span><span style="font-family: 宋体;">、版本、提供商、</span><span lang="EN-US">classpath</span><span style="font-family: 宋体;">、所依赖的</span><span lang="EN-US">plugin</span><span style="font-family: 宋体;">以及可暴露对外的包均在</span><span lang="EN-US">manifest.mf</span><span style="font-family: 宋体;">文件中定义。</span><span lang="EN-US"><br>Plugin Extension Point<br></span><span style="font-family: 宋体;">对</span> 
<span style="font-family: 宋体;">于扩展，</span><span lang="EN-US">Eclipse</span><span style="font-family: 宋体;">采用</span><span lang="EN-US">Extension Point</span><span style="font-family: 宋体;">的方式来实现，每个</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">可定义自己的</span><span lang="EN-US">Extension Point</span><span style="font-family: 宋体;">，同时也可实现其他</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">的</span><span lang="EN-US">Extension Point</span><span style="font-family: 宋体;">，由于这个在</span><span lang="EN-US">OSGI</span><span style="font-family: 宋体;">中是未定义的，在</span><span lang="EN-US">Eclipse</span><span style="font-family: 宋体;">中仍然通过在</span><span lang="EN-US">plugin.xml</span><span style="font-family: 宋体;">中进行描述，描述的方法为通过</span><span lang="EN-US">&lt; extension-point id="" name="" schema=""&gt;</span><span style="font-family: 宋体;">的形式来定义</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">的扩展点，通过</span><span lang="EN-US"><EXTENSION point=""></EXTENSION></span><span style="font-family: 宋体;">的形式来定义实现的其他</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">的扩展点，所提供的扩展点通过</span><span lang="EN-US">schema</span><span style="font-family: 宋体;">的方式进行描述，详细见</span><span lang="EN-US">eclipse extension-point schema</span><span style="font-family: 宋体;">规范，为了更好的说明扩展点这个概念，举例如下，如工具栏就是工具栏</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">提供的一个扩展点，其他的</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">可通过此扩展点添加按</span> 
<span style="font-family: 宋体;">钮至工具栏中，并可相应的添加按钮所对应的事件</span><span lang="EN-US">(</span><span style="font-family: 宋体;">当然，此事件必须实现工具栏</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">此扩展点所要求的接口</span><span lang="EN-US">)</span><span style="font-family: 宋体;">，工具栏的</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">将通过</span><span lang="EN-US"> callback</span><span style="font-family: 宋体;">的方式来相应的响应按钮的动作。可见通过</span><span lang="EN-US">Extension Point</span><span style="font-family: 宋体;">的方式可以很好的提供</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">的扩展方式以及实现扩展的方式。</span><span lang="EN-US"><o:p></o:p></span></p>

<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><b><span lang="EN-US">Eclipse 
Plugin Framework</span></b><span lang="EN-US"><br></span><span style="font-family: 宋体;">那</span> 
<span style="font-family: 宋体;">么</span><span lang="EN-US">Eclipse</span><span style="font-family: 宋体;">是如何做到</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">机制的实现的呢？？还是先讲讲</span><span lang="EN-US">Eclipse</span><span style="font-family: 宋体;">的设计风格，</span><span lang="EN-US">Eclipse</span><span style="font-family: 宋体;">在设计时有个重要的分层法则，即语言层相</span> 
<span style="font-family: 宋体;">关和语言层无关的代码分开</span><span lang="EN-US">(</span><span style="font-family: 宋体;">如</span><span lang="EN-US">jdt.core</span><span style="font-family: 宋体;">和</span><span lang="EN-US">core)</span><span style="font-family: 宋体;">，核心与</span><span lang="EN-US">UI</span><span style="font-family: 宋体;">分开</span><span lang="EN-US">(</span><span style="font-family: 宋体;">如</span><span lang="EN-US">workbench.ui</span><span style="font-family: 宋体;">和</span><span lang="EN-US">workbench.core)</span><span style="font-family: 宋体;">这两个分层法</span> 
<span style="font-family: 宋体;">则，这个在</span><span lang="EN-US">Eclipse</span><span style="font-family: 宋体;">代码中处处可见，在</span><span lang="EN-US">Plugin Framework</span><span style="font-family: 宋体;">部分也充分得体现了这个，遵循</span><span lang="EN-US">OSGI</span><span style="font-family: 宋体;">，</span><span lang="EN-US">Eclipse</span><span style="font-family: 宋体;">首先是实现了一个</span><span lang="EN-US">OSGI Impl</span><span style="font-family: 宋体;">，这个主要通过它的</span><span lang="EN-US">FrameWork</span><span style="font-family: 宋体;">、</span><span lang="EN-US">BundleHost</span><span style="font-family: 宋体;">、</span><span lang="EN-US">ServiceRegistry</span><span style="font-family: 宋体;">、</span><span lang="EN-US">BundleContextImpl</span><span style="font-family: 宋体;">等对象来实</span> 
<span style="font-family: 宋体;">现，如果关心的话大家可以看看这部分的代码，实现了</span><span lang="EN-US">Bundle</span><span style="font-family: 宋体;">的安装、触发、卸载以及</span><span lang="EN-US">Service</span><span style="font-family: 宋体;">的注册、卸载、调用，在</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">机制上</span><span lang="EN-US"> Eclipse</span><span style="font-family: 宋体;">采用的为</span><span lang="EN-US">lazy load</span><span style="font-family: 宋体;">的方式，即在调用时才进行实际的启动，采用的为句柄</span><span lang="EN-US">/</span><span style="font-family: 宋体;">实体的方式来实现，外部则通过</span><span lang="EN-US">OSGI</span><span style="font-family: 宋体;">进行启动、停止等动作，各</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">则通过</span><span lang="EN-US"> BundleContext</span><span style="font-family: 宋体;">来进行服务的注册、卸载和调用，这是</span><span lang="EN-US">OSGI</span><span style="font-family: 宋体;">的部分实现的简单介绍。</span><span lang="EN-US"><br></span><span style="font-family: 宋体;">那么</span><span lang="EN-US">Extension Point</span><span style="font-family: 宋体;">方面</span><span lang="EN-US">Eclipse</span><span style="font-family: 宋体;">是如何实现的呢，在加载</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">时，</span><span lang="EN-US">Eclipse</span><span style="font-family: 宋体;">通过对</span><span lang="EN-US">plugin.xml</span><span style="font-family: 宋体;">的解析获取其中的</span><span lang="EN-US">&lt; extension-point&gt;</span><span style="font-family: 宋体;">节点和</span><span lang="EN-US"><EXTENSION></EXTENSION></span><span style="font-family: 宋体;">节点，并相应的注册到</span><span lang="EN-US">ExtensionRegistry</span><span style="font-family: 宋体;">中，而各个提</span> 
<span style="font-family: 宋体;">供扩展点的</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">在提供扩展点的地方进行处理，如工具栏</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">提供了工具栏的扩展点，那么在构成工具栏时</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">将通过</span><span lang="EN-US"> Platform.getPluginRegistry().getExtensionPoint(</span><span style="font-family: 宋体;">扩展点</span><span lang="EN-US">ID)</span><span style="font-family: 宋体;">的方法获取所有实现此扩展点的集合</span><span lang="EN-US"> IExtensionPoint[]</span><span style="font-family: 宋体;">，通过此集合可获取</span><span lang="EN-US">IConfigurationElement[]</span><span style="font-family: 宋体;">，而通过这个就可以获取</span><span lang="EN-US">&lt; extension point=""&gt;</span><span style="font-family: 宋体;">其中的配置，同时还可通过</span><span lang="EN-US">IConfigurationElement</span><span style="font-family: 宋体;">创建回调对象的实例，通过这样的方法</span><span lang="EN-US">Eclipse</span><span style="font-family: 宋体;">也就实</span> 
<span style="font-family: 宋体;">现了对于</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">的扩展以及扩展的功能的回调。在</span><span lang="EN-US">Plugin Framework</span><span style="font-family: 宋体;">中还涉及很多事件机制的使用，比如</span><span lang="EN-US">Framework</span><span style="font-family: 宋体;">的事件机制，以便在</span><span lang="EN-US">Bundle</span><span style="font-family: 宋体;">注册、</span><span lang="EN-US">Service</span><span style="font-family: 宋体;">注册的时候进行通知。</span><span lang="EN-US"><o:p></o:p></span></p>

<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><b><span style="font-family: 宋体;">总结</span></b><span lang="EN-US"><br></span><span style="font-family: 宋体;">通</span> 
<span style="font-family: 宋体;">过对</span><span lang="EN-US">Eclipse</span><span style="font-family: 宋体;">启动过程的分析，可清晰的看到</span><span lang="EN-US">Eclipse Kernel+Core Plugins+Application Plugins</span><span style="font-family: 宋体;">的方式，在代码中分别对应为</span><span lang="EN-US">loadBasicBundles</span><span style="font-family: 宋体;">和</span><span lang="EN-US">registerApplicationServices</span><span style="font-family: 宋体;">，</span><span lang="EN-US"> loadBasicBundles</span><span style="font-family: 宋体;">通过加载</span><span lang="EN-US">config.ini</span><span style="font-family: 宋体;">中的</span><span lang="EN-US">osgi.bundles</span><span style="font-family: 宋体;">完成基本的</span><span lang="EN-US">bundles</span><span style="font-family: 宋体;">的加载，去看看这个配置会发现是</span><span lang="EN-US"> org.eclipse.core.runtime</span><span style="font-family: 宋体;">还有一个</span><span lang="EN-US">update</span><span style="font-family: 宋体;">，</span><span lang="EN-US">core.runtime</span><span style="font-family: 宋体;">又会通过</span><span lang="EN-US">IDEApplication</span><span style="font-family: 宋体;">来完成整个</span><span lang="EN-US"> Eclipse</span><span style="font-family: 宋体;">的启动，同时会注册所有与</span><span lang="EN-US">workbench</span><span style="font-family: 宋体;">相关的</span><span lang="EN-US">plugin</span><span style="font-family: 宋体;">。</span><span lang="EN-US"><br>Eclipse</span><span style="font-family: 宋体;">由于以前版本的</span><span lang="EN-US">Plugin Framework</span><span style="font-family: 宋体;">是没有采用</span><span lang="EN-US">OSGI</span><span style="font-family: 宋体;">的，所以通过</span><span lang="EN-US">EclipseAdaptor</span><span style="font-family: 宋体;">的方式来实现与以往的兼容，目前新的</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">采用的方式基本就是</span><span lang="EN-US"> manifest.mf</span><span style="font-family: 宋体;">描述</span><span lang="EN-US">Plugin OSGI</span><span style="font-family: 宋体;">部分的信息，</span><span lang="EN-US">Plugin.xml</span><span style="font-family: 宋体;">描述扩展点的信息。</span><span lang="EN-US"><br>Eclipse</span><span style="font-family: 宋体;">中有非常多优秀的设计，这</span> 
<span style="font-family: 宋体;">个在看它的代码时会有很深的感触，比如</span><span lang="EN-US">Contributing to Eclipse</span><span style="font-family: 宋体;">中提到的</span><span lang="EN-US">Extension Object/Interface</span><span style="font-family: 宋体;">的设计，确实是非常的不错，虽然看到你可能觉得很简单，关键是要想得到并合适的去使用。</span><span lang="EN-US"><br></span><span style="font-family: 宋体;">总结陈词，</span><span lang="EN-US">^_^</span><span style="font-family: 宋体;">，</span><span lang="EN-US"> Eclipse Plugin Framework</span><span style="font-family: 宋体;">是采用</span><span lang="EN-US">OSGI Impl+Plugin Extension-Point</span><span style="font-family: 宋体;">的方式来共同实现的，实现了</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">的部署、编写、独立的</span><span lang="EN-US">Classloader</span><span style="font-family: 宋体;">和</span><span lang="EN-US">Context</span><span style="font-family: 宋体;">、</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">中</span><span lang="EN-US"> Service</span><span style="font-family: 宋体;">的注册、</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">中</span><span lang="EN-US">Service</span><span style="font-family: 宋体;">的调用、</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">的依赖、</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">的扩展、</span><span lang="EN-US">Plugin</span><span style="font-family: 宋体;">生命周期的管理。</span><span lang="EN-US"><o:p></o:p></span></p>

<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><b><span style="font-family: 宋体;">带来的思考</span><span lang="EN-US"><br></span></b><span lang="EN-US">Eclipse Plugin Framework</span><span style="font-family: 宋体;">采用的是</span><span lang="EN-US">OSGI</span><span style="font-family: 宋体;">的实现，一定程度上我们也能看到</span><span lang="EN-US">OSGI</span><span style="font-family: 宋体;">的优点，那么</span><span lang="EN-US">JMX+IoC</span><span style="font-family: 宋体;">方式的</span><span lang="EN-US">Plugin Framework</span><span style="font-family: 宋体;">与其的比较又是在哪些方面呢？</span><span lang="EN-US">Eclipse Plugin Framework</span><span style="font-family: 宋体;">不足的地方又在哪里呢？哪些地方值得改进呢？</span><span lang="EN-US"><o:p></o:p></span></p>

<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span lang="EN-US">&nbsp;<o:p></o:p></span></p>

<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<img src ="http://www.blogjava.net/ultramarine/aggbug/13827.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ultramarine/" target="_blank">ultramarine</a> 2005-09-23 11:52 <a href="http://www.blogjava.net/ultramarine/articles/13827.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ZT:规则显示英文段落 </title><link>http://www.blogjava.net/ultramarine/articles/13821.html</link><dc:creator>ultramarine</dc:creator><author>ultramarine</author><pubDate>Fri, 23 Sep 2005 03:19:00 GMT</pubDate><guid>http://www.blogjava.net/ultramarine/articles/13821.html</guid><wfw:comment>http://www.blogjava.net/ultramarine/comments/13821.html</wfw:comment><comments>http://www.blogjava.net/ultramarine/articles/13821.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ultramarine/comments/commentRss/13821.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ultramarine/services/trackbacks/13821.html</trackback:ping><description><![CDATA[<DIV class=entity><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT>
<DIV class=diaryContent id=diary297748 style="DISPLAY: block"><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT>
<P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0>这是一个规则<FONT size=+0>(</FONT>即折行时不能拦腰截断单个单词<FONT size=+0>)</FONT><SPAN>显示英文段落的例子,使用的JDK版本是1.3.</SPAN></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></P>
<P><SPAN>
<HR>
</SPAN>
<P></P>
<HR>

<P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT> </P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><BR></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT>
<P></P>
<P><SPAN><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0>我在实践中曾遇到这样一个问题</FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></SPAN><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0>,</FONT>即<FONT size=+0>,</FONT>把从<FONT size=+0>MySQL</FONT>数据库拿到的<FONT size=+0>TEXT</FONT><SPAN>类型的英文字符按照指定的单行显示长度规则地</SPAN><FONT size=+0>(</FONT>即折行时不能拦腰截断单个单词<FONT size=+0>)</FONT><SPAN>显示在画面上</SPAN><FONT size=+0>.<BR></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></P>
<P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0>由于当时的实际情况是用<FONT size=+0>JDK1.3</FONT>的方式解决<FONT size=+0>,</FONT>所以当时还真的费了些脑筋<FONT size=+0>,</FONT>解决这个问题大概花了两个小时<FONT size=+0>.</FONT>下面就是例程<FONT size=+0>.</FONT>其基本思路是<FONT size=+0>,</FONT>先按空格取出字符串中的单词<FONT size=+0>,</FONT>再按指定的长度把单词拼成行<FONT size=+0>.<BR></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT>
<P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0>/*<BR> * Copyright (c) 2004 zhangzengzhi<BR> * All rights reserved.<BR> * $<BR> */<BR>import java.util.ArrayList;<BR>import java.util.List;<BR>/**<BR> * @author 张增志---zhangzengzhi<BR> * @version 1.0 2004/11/29 Created initially.<BR> * <BR> * EnWordsTest.java<BR> *<BR> */<BR>public class EnWordsTest {<BR>    private static List wordsList = new ArrayList();<BR>    private static List enWordsList = new ArrayList();<BR>    private static void resolveEnWords(String p_sentence) {<BR>        String sentence = p_sentence;<BR>        if (p_sentence.indexOf(" ") != -1) {<BR>            int i_comma = sentence.indexOf(" ");<BR>            String temp = sentence.substring(0, i_comma);<BR>            wordsList.add(temp);<BR>            sentence = sentence.substring(i_comma + 1, p_sentence.length());<BR>            resolveEnWords(sentence);<BR>        } else {<BR>            wordsList.add(sentence);<BR>        }<BR>    }<BR>    private static List getWordsList(String p_sentence) {<BR>        wordsList.clear();<BR>        resolveEnWords(p_sentence);<BR>        return wordsList;<BR>    }<BR>    private static void splitEnWordsToList(List wordsList, int len) {<BR>        List t_list = wordsList;<BR>        String t_word = "";<BR>        int word_len = 0;<BR>        for (int i = 0; i < t_list.size(); i++) {<BR>            String word = (String) t_list.get(i);<BR>            word_len += word.length() + 1;<BR>            if (word_len <= len) {<BR>                t_word = t_word + word + " ";<BR>                if (i == t_list.size() - 1) {<BR>                    enWordsList.add(t_word.trim());<BR>                    return;<BR>                }<BR>            } else {<BR>                word_len = 0;<BR>                enWordsList.add(t_word);<BR>                splitEnWordsToList(t_list.subList(i, t_list.size()), len);<BR>                return;<BR>            }<BR>        }<BR>    }<BR>    /**<BR>     * split a English String to List according to specific length.<BR><BR>     * <BR>     * Bug1: len < word.length() then throw java.lang.StackOverflowError <BR><BR>     * <BR>     * @param p_sentence English String<BR>     * @param len display length of one line<BR>     * @return String List<BR>     */<BR>    public static List getSplitEnWordsList(String p_sentence, int len) {<BR>        enWordsList.clear();<BR>        if (p_sentence != null && !p_sentence.equals("")) {<BR>            List words = getWordsList(p_sentence);<BR>            if (words.size() == 1) {<BR>                return words;<BR>            }<BR>            splitEnWordsToList(words, len);<BR>        }<BR>        return enWordsList;<BR>    }<BR>}<BR>上述例程中已知的一个<FONT size=+0>BUG</FONT>是单行显示长度如小于某个英文单词的长度<FONT size=+0>,</FONT>就会出错<FONT size=+0>.</FONT>但是这种情况在实际中出现的可能性几乎没有<FONT size=+0>,</FONT>所以当时就只作记录而忽略处理了<FONT size=+0>.</FONT> </FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></DIV></DIV><img src ="http://www.blogjava.net/ultramarine/aggbug/13821.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ultramarine/" target="_blank">ultramarine</a> 2005-09-23 11:19 <a href="http://www.blogjava.net/ultramarine/articles/13821.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ZT:WebOTX中的JNDI实践 </title><link>http://www.blogjava.net/ultramarine/articles/13822.html</link><dc:creator>ultramarine</dc:creator><author>ultramarine</author><pubDate>Fri, 23 Sep 2005 03:19:00 GMT</pubDate><guid>http://www.blogjava.net/ultramarine/articles/13822.html</guid><wfw:comment>http://www.blogjava.net/ultramarine/comments/13822.html</wfw:comment><comments>http://www.blogjava.net/ultramarine/articles/13822.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ultramarine/comments/commentRss/13822.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ultramarine/services/trackbacks/13822.html</trackback:ping><description><![CDATA[<DIV class=entity><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT>
<DIV class=diaryContent id=diary274048 style="DISPLAY: block"><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0>WebOTX是NEC公司的Application Server产品.我使用的版本是5.3.它的Web Container是Tomcat4.0.<SPAN>在</SPAN><SPAN>WebOTX</SPAN><SPAN>中配置</SPAN><SPAN>JNDI</SPAN><SPAN>数据源曾经颇费周折</SPAN><SPAN>.</SPAN><SPAN>下面就简单介绍其中的一个方面</SPAN><SPAN>.</SPAN></FONT><BR>一般来说<FONT size=+0>,</FONT>只要在服务器端进行正确的配置<FONT size=+0>,</FONT>从<FONT size=+0>JNDI</FONT>中拿到的对象是不会出现问题的<FONT size=+0>.</FONT>但是<FONT size=+0>,</FONT>如果服务器本身就是有缺失的<FONT size=+0>,</FONT>如它在启动的过程中少装载一个<FONT size=+0>JAR</FONT>包<FONT size=+0>,</FONT>或者说服务器自身环境配置就存在问题<FONT size=+0>,</FONT>那就有可能出现意想不到的情况<FONT size=+0>.<BR></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT>
<P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0>在服务器中配置<FONT size=+0>JNDI</FONT>数据源<FONT size=+0>(javax.sql.DataSource)</FONT>时<FONT size=+0>,</FONT>不同的服务器中<FONT size=+0>lookup</FONT>得到的<FONT size=+0>Object</FONT>是不同的<FONT size=+0>.</FONT>在<FONT size=+0>Tomcat5</FONT>中得到的是<FONT size=+0>org.apache.commons.dbcp.BasicDataSource</FONT>类<FONT size=+0>,</FONT>在<FONT size=+0>Jboss3.2</FONT>中得到的是<FONT size=+0>org.jboss.resource.adapter.jdbc.WrapperDataSource</FONT>类<FONT size=+0>,</FONT>在<FONT size=+0>WebOTX5.3</FONT>中得到的是<FONT size=+0>jp.co.nec.WebOTX.WODataSource</FONT>类<FONT size=+0>.</FONT>所有的这些类都实现了<FONT size=+0>javax.sql.DataSource</FONT>接口<FONT size=+0>,</FONT>所以我们才可以<FONT size=+0>Cast</FONT>这个<FONT size=+0>Object</FONT>为<FONT size=+0>javax.sql.DataSource.<BR></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT>
<P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0>但是<FONT size=+0>,</FONT>如果服务器启动时<FONT size=+0>,</FONT>它的类装载系统没有导入包含这些类的<FONT size=+0>JAR</FONT>包<FONT size=+0>,</FONT>那么<FONT size=+0>,</FONT>不同的服务器就会出不同的错误<FONT size=+0>.<BR></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT>
<P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0>对于<FONT size=+0>Tomcat,</FONT>错误发生在实际动作时<FONT size=+0>,</FONT>即<FONT size=+0>lookup</FONT>方法被调用的地方<FONT size=+0>.</FONT>它会出一个<FONT size=+0>ClassNotFoundException</FONT>异常<FONT size=+0>.<BR></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT>
<P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0>对于<FONT size=+0>JBoss,</FONT>错误发生在服务器启动时<FONT size=+0>(</FONT>错误的原因就是类缺失<FONT size=+0>).</FONT>也就是说<FONT size=+0>,JBoss</FONT>中的对象<FONT size=+0>Bind</FONT>动作是在<SPAN>服务器</SPAN>启动时完成的<FONT size=+0>.</FONT>如果在发生服务器启动错误的情况下仍然进行<FONT size=+0>lookup</FONT>动作<FONT size=+0>,</FONT>就会出现<FONT size=+0>javax.naming.NameNotFoundException</FONT>异常<FONT size=+0>.<BR></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT>
<P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0>对于<FONT size=+0>WebOTX,</FONT>错误也是发生在实际动作时<FONT size=+0>.</FONT>但是它和<FONT size=+0>Tomcat</FONT>不同的是<FONT size=+0>,</FONT>它出一个<FONT size=+0>ClassCastException</FONT>异常<FONT size=+0>.</FONT>这个异常说明不是类装载器的问题<FONT size=+0>,</FONT>而是的确<FONT size=+0>lookup</FONT>到了一个<FONT size=+0>Object,</FONT>但这个<FONT size=+0>Object</FONT>不是<FONT size=+0>javax.sql.DataSource</FONT>接口<FONT size=+0>.</FONT>就像前面所说的<FONT size=+0>,</FONT>得不到<FONT size=+0>DataSource</FONT>的真正原因就是由于类路径<FONT size=+0>(</FONT>是指类装载器委托模型中的类<FONT size=+0>,</FONT>它并不等同于<FONT size=+0>CLASSPATH,</FONT>相反<FONT size=+0>CLASSPATH</FONT>只是其中的一部分<FONT size=+0>)</FONT>不全<FONT size=+0>,</FONT>这说明在<FONT size=+0>WebOTX</FONT>中<FONT size=+0>lookup</FONT>时抛出的<FONT size=+0>ClassCastException</FONT>异常掩盖了原始的异常信息<FONT size=+0>.</FONT>掩盖的根本原因是<FONT size=+0>,</FONT>原始的异常信息被<FONT size=+0>WebOTX</FONT>服务器处理了<FONT size=+0>,</FONT>并且处理后并没有把异常信息告诉它的客户程序<FONT size=+0>.<BR></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT>
<P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0>Java</FONT>异常处理的一个规则就是不要遮蔽异常<FONT size=+0>.</FONT>因为一旦出现这种情况<FONT size=+0>,</FONT>而客户程序又非常想知道错误原因<FONT size=+0>,</FONT>那么就可能丢失问题真正原因的线索<FONT size=+0>.<BR></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT>
<P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0>这个错误也提供了一个<FONT size=+0>WebOTX5.3</FONT><SPAN>不成熟的证据</SPAN><FONT size=+0>.<BR></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT>
<P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0>出现这种情况<FONT size=+0>,</FONT>就只能从<FONT size=+0>lookup</FONT>得到的<FONT size=+0>Object</FONT>来查找线索了<FONT size=+0>.</FONT>结果发现<FONT size=+0>Object</FONT>是<FONT size=+0>javax.naming.Reference</FONT>对象<FONT size=+0>,</FONT><SPAN>这就说明了错误是由</SPAN>类路径不全造成的<FONT size=+0>.</FONT>但是又暴露了<FONT size=+0>WebOTX</FONT>的另外一个问题<FONT size=+0>---</FONT>类装载器<FONT size=+0>.<BR></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT>
<P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0>一个设计良好的应用框架系统<FONT size=+0>,</FONT>是有必要建立自己的类装载系统的<FONT size=+0>,</FONT>而不能过分依赖系统<FONT size=+0>CLASSPATH</FONT>变量<FONT size=+0>.</FONT>例如<FONT size=+0>,Tomcat</FONT>有自己的类装载机制<FONT size=+0>,JBoss</FONT>也是<FONT size=+0>.Eclipse</FONT>则干脆不用系统<FONT size=+0>CLASSPATH</FONT>变量<FONT size=+0>.</FONT>具体信息请参照它们的文档<FONT size=+0>.<BR></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT>
<P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0>如果过分依赖<FONT size=+0>CLASSPATH,</FONT>就会有一个副作用<FONT size=+0>,</FONT>就是造成自身系统的不稳定<FONT size=+0>.</FONT>因为<FONT size=+0>CLASSPATH</FONT>是开放的<FONT size=+0>,</FONT>无法确保其它应用对它的修改不会对自身系统产生负面影响<FONT size=+0>.<BR></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT>
<P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0>WebOTX 就是一例.它的Web Container就是Tomcat,除了把一些JAR包放在了Tomcat认可的目录下外,它把有些JAR包就设置到了系统CLASSPATH变量下. 造成的问题就是,连启动它的Web Container都成了一件困难的事情.这又是一个证据. </FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></DIV></DIV><img src ="http://www.blogjava.net/ultramarine/aggbug/13822.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ultramarine/" target="_blank">ultramarine</a> 2005-09-23 11:19 <a href="http://www.blogjava.net/ultramarine/articles/13822.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> ZT:Struts1.1源码学习 </title><link>http://www.blogjava.net/ultramarine/articles/13820.html</link><dc:creator>ultramarine</dc:creator><author>ultramarine</author><pubDate>Fri, 23 Sep 2005 03:18:00 GMT</pubDate><guid>http://www.blogjava.net/ultramarine/articles/13820.html</guid><wfw:comment>http://www.blogjava.net/ultramarine/comments/13820.html</wfw:comment><comments>http://www.blogjava.net/ultramarine/articles/13820.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ultramarine/comments/commentRss/13820.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ultramarine/services/trackbacks/13820.html</trackback:ping><description><![CDATA[<H5 class=diaryTitle>&nbsp;</H5>
<DIV class=diaryContent id=diary316017 style="DISPLAY: block"><SPAN><FONT size=+0>Struts1.1</FONT>源码中有很多闪光点</SPAN><SPAN>,</SPAN><SPAN>本文就简单介绍</SPAN><SPAN>Action</SPAN><SPAN>类中的一个闪光点</SPAN><SPAN>.</SPAN><BR><FONT size=+0>Action</FONT>是<FONT size=+0>Struts1.1</FONT><SPAN>框架中最富有弹性的类</SPAN><FONT size=+0>.</FONT>它的主要职责是<FONT size=+0>:<BR></FONT><FONT size=+0>1.</FONT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 访问业务层<BR><FONT size=+0>2.</FONT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为表示层准备数据对象<BR><FONT size=+0>3.</FONT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 处理上两项中可能发生的错误<BR>它有两个特点<FONT size=+0>:<BR></FONT><FONT size=+0>1.</FONT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在一个<FONT size=+0>Struts1.1</FONT>应用中<FONT size=+0>,</FONT>每一个<FONT size=+0>Action</FONT>类都只有一个实例<FONT size=+0>.<BR></FONT><FONT size=+0>2.</FONT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 有条件的线程安全<FONT size=+0>.<BR></FONT>
<P><FONT size=+0></FONT></P><FONT size=+0>本文的目的主要是说明<FONT size=+0>Struts1.1</FONT>应用中的<FONT size=+0>"</FONT>每一个<FONT size=+0>Action</FONT>类都只有一个实例<FONT size=+0>"</FONT>这个特点是如何实现的<FONT size=+0>,</FONT>以对以后的工作有所启示<FONT size=+0>.</FONT>对于上文中的第二个特点<FONT size=+0>,</FONT>由于对<FONT size=+0>"</FONT>线程安全<FONT size=+0>"</FONT>这个命题<FONT size=+0>(</FONT>或概念<FONT size=+0>)</FONT>还存在争议<FONT size=+0>,</FONT>所以本文不作讨论<FONT size=+0>,</FONT>关于对它的讨论请参照<A href="http://www.uml.org.cn/j2ee/j2ee110601.htm"><FONT size=+0>http://www.uml.org.cn/j2ee/j2ee110601.htm</FONT></A><BR></FONT>
<P><FONT size=+0><FONT size=+0></FONT></FONT></P><FONT size=+0><FONT size=+0>我们知道<FONT size=+0>,</FONT>在<FONT size=+0>Struts</FONT>配置文件中配置了每一个<FONT size=+0>Action</FONT>类的全限定名<FONT size=+0>.Struts</FONT>中的请求处理器<FONT size=+0>(org.apache.struts.action.RequestProcessor)</FONT>类<FONT size=+0>,</FONT>首先取得<FONT size=+0>HTTP</FONT>请求中的<FONT size=+0>PATH</FONT>值<FONT size=+0>,</FONT>并根据该值来获取相应的<FONT size=+0>Action</FONT>类的全限定名<FONT size=+0>,</FONT>因为在配置文件中一个<FONT size=+0>Action</FONT>类唯一对应一个<FONT size=+0>PATH</FONT>值<FONT size=+0>.<BR></FONT></FONT></FONT>
<P><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></P><FONT size=+0><FONT size=+0><FONT size=+0>第二<FONT size=+0>,</FONT>根据<FONT size=+0>Action</FONT>类的全限定名<FONT size=+0>,</FONT>从一个<FONT size=+0>java.util.HashMap</FONT>中获取该<FONT size=+0>Action</FONT>类的实例对象<FONT size=+0>.</FONT>如果取得的实例对象非<FONT size=+0>NULL,</FONT>则返回该对象<FONT size=+0>.<BR></FONT></FONT></FONT></FONT>
<P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0>第三<FONT size=+0>,</FONT>如果上一步取得的实例对象为<FONT size=+0>NULL,</FONT>则根据<FONT size=+0>Action</FONT>类的全限定名从类装载系统中导入并实例化<FONT size=+0>.<BR></FONT></FONT></FONT></FONT></FONT>
<P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></FONT></P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0>第四<FONT size=+0>,</FONT>把从上一步中获得的<FONT size=+0>Action</FONT>类实例根据类的全限定名缓存在<FONT size=+0>java.util.HashMap</FONT>中<FONT size=+0>.<BR></FONT></FONT></FONT></FONT></FONT></FONT>
<P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></FONT></FONT></P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0>代码实现如下<FONT size=+0>:<BR></FONT></FONT></FONT></FONT></FONT></FONT></FONT>
<P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></FONT></FONT></FONT></P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0>protected Action processActionCreate(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpServletRequest request,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpServletResponse response,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ActionMapping mapping)<BR>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;throws IOException {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //1.根据请求PATH获取类名<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String className = mapping.getType();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Action instance = null;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (actions) {//actions为java.util.HashMap的实例.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //2.根据类名取得类的实例.actions为java.util.HashMap的实例.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; instance = (Action) actions.get(className);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (instance != null) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (instance);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //3.根据Action类的全限定名从类装载系统中导入并实例化.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; instance = (Action) RequestUtils.applicationInstance(className);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (Exception e) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; response.sendError(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpServletResponse.SC_INTERNAL_SERVER_ERROR,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getInternal().getMessage(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "actionCreate",<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mapping.getPath()));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (null);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; instance.setServlet(this.servlet);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //4.缓存Action类实例.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; actions.put(className, instance);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (instance);<BR>&nbsp;&nbsp;&nbsp; } </FONT></FONT></FONT></FONT></FONT></FONT></FONT>
<P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></P><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0>"</FONT>一个<FONT size=+0>Action</FONT>类只有一个实例<FONT size=+0>"</FONT>的实现<FONT size=+0>,</FONT>简单地说就是<FONT size=+0>,</FONT>缓存每一个被实例化的<FONT size=+0>Action</FONT>类<FONT size=+0>.</FONT> </FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></DIV><img src ="http://www.blogjava.net/ultramarine/aggbug/13820.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ultramarine/" target="_blank">ultramarine</a> 2005-09-23 11:18 <a href="http://www.blogjava.net/ultramarine/articles/13820.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ZT:Eclipse3.0平台简介</title><link>http://www.blogjava.net/ultramarine/articles/13817.html</link><dc:creator>ultramarine</dc:creator><author>ultramarine</author><pubDate>Fri, 23 Sep 2005 02:57:00 GMT</pubDate><guid>http://www.blogjava.net/ultramarine/articles/13817.html</guid><wfw:comment>http://www.blogjava.net/ultramarine/comments/13817.html</wfw:comment><comments>http://www.blogjava.net/ultramarine/articles/13817.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ultramarine/comments/commentRss/13817.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ultramarine/services/trackbacks/13817.html</trackback:ping><description><![CDATA[<!--StartFragment -->
<P>作者:张增志<BR>概要<BR>Eclipse3.0平台与Eclipse2.1平台的一个重要的区别就是,Eclipse3.0平台建立在一个Java框架上,即Open Services Gateway Initiative(OSGi)服务平台.OSGi的采用,使Eclipse<SPAN>走上了完全动态平台的发展道路</SPAN>.本文先简要介绍OSGi框架,然后介绍OSGi框架和Eclipse3.0平台的联系. </P>
<P><BR>一.&nbsp; OSGi框架简介<BR><A href="http://blog.blogchina.com/upload/2004-11-24/20041124110530659453.jpg">URL:http://blog.blogchina.com/upload/2004-11-24/20041124110530659453.jpg</A><BR>图1:Eclipse3.0架构<BR>如上图所示,Eclipse3.0平台是建立在OSGi(Open Services Gateway Initiative)服务平台基础之上的,所以有必要先介绍一下OSGi框架.<BR>OSGi框架<BR>OSGi框架是一个通用,安全,可管理的Java框架,它支持被称为"<EM>bundle</EM>"的可扩展和可下载的服务应用的部署.与OSGi兼容的设备可以下载和安装基于OSGi标准的<EM>bundle</EM>,并且还可以删除不再需要的<EM>bundle</EM>.另外,已安装的<EM>bundle</EM>可以注册一组服务(service),这些服务可以在OSGi框架的严格控制下被其他<EM>bundle</EM>共享.<BR>OSGi框架以一种动态和可升级的方式管理哪些处于OSGi环境中的<EM>bundle</EM>的安装和更新,还管理<EM>bundle</EM>和服务(service)的依赖关系.<BR>Bundle<BR>在OSGi服务平台中,<EM>bundle</EM>是部署的Java应用的唯一实体.一个<EM>bundle</EM>由Java类和其它资源组成,它们提供功能给终端用户,提供服务组件(serveices)给其它的<EM>bundle</EM>.<BR><EM>Bundle</EM>是作为JAR文件被部署的.可以说,一个<EM>bundle</EM>就是一个JAR文件,它包括:<BR>1&gt;&nbsp;&nbsp;&nbsp;&nbsp; 容纳了实现零个或多个服务的资源.这些资源可以是Java类文件,也可以是其它数据文件如HTML文件,图标文件等.<BR>2&gt;&nbsp;&nbsp;&nbsp;&nbsp; 容纳了一个manifest文件.该文件描述了JAR文件的内容和与<EM>bundle</EM>相关的配置信息.<BR>3&gt;&nbsp;&nbsp;&nbsp;&nbsp; 陈述了对其他资源如Java中的包(package)的依赖关系.<BR>4&gt;&nbsp;&nbsp;&nbsp;&nbsp; 指明<EM>bundle</EM>中的一个Java类作为Bundle Activator接口的实现类.OSGi框架必须实例化该类并调用start和stop方法来启动和停止<EM>bundle</EM>.<BR>MANIFEST.MF文件<BR>每一个<EM>bundle</EM>都有一个描述其自身信息的MANIFEST.MF文件,该文件位于JAR文件中的META-INF目录下.<BR>我们知道,在生成普通的Java JAR文件时都会要求指定一个MANIFEST.MF文件与该JAR文件关联在一起.MANIFEST.MF文件的内容格式可能如下:<BR></P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD>
<DIV>
<P><FONT size=+0>Manifest-Version: 1.0</FONT></P>
<P><FONT size=+0>Ant-Version: Apache Ant 1.5.3</FONT></P>
<P><FONT size=+0>Created-By: 1.4.2_04-b05 (Sun Microsystems Inc.)</FONT></P></DIV></TD></TR></TBODY></TABLE><BR>在OSGi框架中,每一个<EM>bundle</EM>的MANIFEST.MF文件除了可以包括上述内容外,还定义了自己的OSGi MANIFEST内容格式,例如:<BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD>
<DIV>
<P><FONT size=+0>Manifest-Version: 1.0</FONT></P>
<P><FONT size=+0>Ant-Version: Apache Ant 1.5.3</FONT></P><FONT size=+0>Created-By: 1.4.2_04-b05 (Sun Microsystems Inc.)<BR></FONT><FONT size=+0>Bundle-Activator: test.osgi.exam2.Activator<BR></FONT><FONT size=+0>Export-Package: test.osgi.exam2.service<BR></FONT><FONT size=+0>Bundle-Name: English dictionary<BR></FONT><FONT size=+0>Bundle-Description: A bundle that registers an English dictionary service<BR></FONT><FONT size=+0>Bundle-Version: 1.0.0<BR></FONT></DIV></TD></TR></TBODY></TABLE>
<P><BR>上例中显示的是一组MANIFEST头(header)/值(value)对,如Bundle-Activator头(header)的值为test.osgi.exam2.Activator.<BR>在OSGi框架定义了一组标准的MANIFEST头(header),每一个header都有其特定的含义.上例中定义的Bundle-Activator头信息的值test.osgi.exam2.Activator表示用来启动和停止"English dictionary" Bundle的类名. Export-Package头信息的值test.osgi.exam2.service表示可以被导出的包名,即test.osgi.exam2.service包可以被其它Bundle导入并使用其中提供的服务(service).<BR>Bundle的受控状态<BR>一个Bundle可能处在下面的状态之中:<BR>■&nbsp;&nbsp;&nbsp;&nbsp; 已安装(installed)<BR>在OSGi框架安装Bundle时,将解析该Bundle的本地代码的依赖关系.如果失败,该Bundle将不会被安装.一旦Bundle被安装,OSGi框架将可对该Bundle的整个生命周期(如起动,停止,更新,卸载)进行控制.<BR>■&nbsp;&nbsp;&nbsp;&nbsp; 已解析(resolved)<BR>当OSGi框架成功地解析Bundle的本地代码的依赖关系时,该Bundle就进入解析状态.这些依赖关系包括:<BR>1&gt;&nbsp;&nbsp;&nbsp;&nbsp; Bundle的MANIFEST.MF文件中,MANIFEST头Bundle-Classpath定义的类路径依赖关系.<BR>2&gt;&nbsp;&nbsp;&nbsp;&nbsp; Bundle的MANIFEST.MF文件中,MANIFEST头Export-Package和Import-Package定义的依赖关系.<BR>■&nbsp;&nbsp;&nbsp;&nbsp; 起动(starting)<BR>一旦Bundle被起动,该Bundle的状态就被设置为ACTIVE,并一直持续到该Bundle被停止.在起动前,MANIFEST.MF文件中MANIFEST头<FONT size=+0>Bundle-Activator</FONT>定义的类将被实例化,该类实例的start方法被调用以起动Bundle.<BR>■&nbsp;&nbsp;&nbsp;&nbsp; 停止(stopping)<BR>一旦Bundle被停止,该Bundle的状态就被设置为RESOLVED.在停止前,上文中提到的<FONT size=+0>Bundle-Activator</FONT>类定义的<FONT size=+0>stop</FONT>方法被调用以停止Bundle.<BR>■&nbsp;&nbsp;&nbsp;&nbsp; 激活(active)<BR>已经被激活的Bundle可以进行自身状态的更新.在任何时候,OSGi框架只能满足一个Bundle的唯一版本可用.Bundle的更新操作支持该Bundle移植到一个高版本或向后兼容的版本.<BR>■&nbsp;&nbsp;&nbsp;&nbsp; 已卸载(uninstalled)<BR>在卸载前,上文中提到的<FONT size=+0>Bundle-Activator</FONT>类定义的<FONT size=+0>uninstall</FONT>方法被调用以卸载Bundle,该方法将使OSGi框架提醒其他<FONT size=+0>Bundle</FONT>它正在进行卸载操作,并设置该Bundle的状态为UNINSTALL.如果该Bundle与其他<FONT size=+0>Bundle</FONT>存在关系<FONT size=+0>,</FONT>如它导出一些被其他<FONT size=+0>Bundle</FONT>使用的包<FONT size=+0>(</FONT>即该Bundle的<FONT size=+0>MANIFEST</FONT>文件中定义了<FONT size=+0>Export-Package</FONT>值<FONT size=+0>),</FONT>OSGi框架在没有被重启的情况下将继续确保这些包仍可用.如果该Bundle与其他<FONT size=+0>Bundle</FONT>没有关系<FONT size=+0>,</FONT>OSGi框架将恢复到该Bundle被安装前的状态.<BR>下面的Bundle状态图描述了Bundle的受控状态.<BR><A href="http://blog.blogchina.com/upload/2004-11-24/20041124110552991489.jpg">URL:http://blog.blogchina.com/upload/2004-11-24/20041124110552991489.jpg</A><BR>图2<BR>类装载(Class Loading)<BR>Bundle就是一个JAR文件,OSGi框架所面临的首要问题就是,怎样去获取随时可能被"扔进"框架中的Bundle内的类文件和其它资源.<BR>对于每一个已安装或已解析的Bundle,OSGi框架都会建立该Bundle的Classloader.这个Classloader还被建立在下面图3所示的委托模型中.<BR><A href="http://blog.blogchina.com/upload/2004-11-24/20041124110606586667.jpg">URL:http://blog.blogchina.com/upload/2004-11-24/20041124110606586667.jpg</A><BR>图3<BR>其中:<BR>1&gt;&nbsp;&nbsp;&nbsp;&nbsp; Bootstrap类装载器装载Java核心API中的类.<BR>2&gt;&nbsp;&nbsp;&nbsp;&nbsp; SystemClassLoader类装载器可以是系统类路径类装载器和标准扩展类装载器,还可以是其他用户自定义类装载器,装载系统CLASSPATH上的类或Java扩展路径上的类或用户指定的类.<BR>3&gt;&nbsp;&nbsp;&nbsp;&nbsp; BundleClassLoader类装载器装载该Bundle的MANIFEST文件中Bundle-ClassPath头所指定的类文件.如果该Bundle需要导入其它Bundle中导出的包,那么这些Bundle的类装载器的实例也要被建立在如图3所示的委托模型中,并为该Bundle提供它所需的类.<BR>上文中只是对OSGi框架进行了简短地介绍,关于它的详细信息请参照:<FONT size=+0> </FONT><A href="http://www.osgi.org/">http://www.osgi.org</A><BR>二.&nbsp; Eclipse3.0插件和OSGi Bundle<BR>OSGi服务平台规范是一个开放的架构,用户可以根据自己的需要来实现这个规范.Eclipse3.0就提供了该规范的一个实现.<BR>我们知道,在OSGi中基本的模块单元是Bundle,在Eclipse中则是插件(plug-in).在Eclipse2.1中,插件往往表现为plugins目录下的一个文件夹.例如如下的目录结构:<BR>&nbsp;&nbsp;&nbsp; + D:\eclipse<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + plugins<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + eclipseme<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + docs<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + icons<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + lib<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - about.html<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - CHANGES.txt<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - CREDITS.txt<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - eclipseme.jar<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - JETTY-LICENSE.html<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - LICENSE.txt<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - plugin.properties<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - plugin.xml<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - README.txt<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - toc.xml<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + org.apache.ant_1.5.3<BR>上述eclipseme插件提供了Eclipse2.1平台和J2ME的集成.在每一个Eclipse2.1插件中,都包含一个plugin.xml文件,其中描述了插件名,版本号,需要的JAR包和插件要使用的扩展点等等.<BR>■ plugin.xml&nbsp;&nbsp; 插件清单文件<BR>■ plugin.properties&nbsp;&nbsp; 容纳被plugin.xml引用的字符串.<BR>■&nbsp;&nbsp;&nbsp;&nbsp; about.html&nbsp;&nbsp; 证书信息<BR>■&nbsp;&nbsp;&nbsp;&nbsp; *.jar&nbsp;&nbsp; 插件需要的类文件<BR>■&nbsp;&nbsp;&nbsp;&nbsp; lib&nbsp;&nbsp; 容纳第三方JAR包<BR>■&nbsp;&nbsp;&nbsp;&nbsp; icons&nbsp;&nbsp; 容纳icon文件,通常是GIF格式<BR>■&nbsp;&nbsp;&nbsp;&nbsp; docs&nbsp;&nbsp; 容纳文档文件,通常是HTML格式<BR>■&nbsp;&nbsp;&nbsp;&nbsp; toc.xml&nbsp;&nbsp; 文档结构清单文件<BR>■&nbsp;&nbsp;&nbsp;&nbsp; (other files)<BR>在Eclipse3.0中,插件不仅表现为plugins目录下的一个文件夹,还包括一个MF文件.这个MF文件可以位于该插件文件夹下.也可位于configuration\org.eclipse.osgi\manifests目录下.如:<BR>例1:<BR>&nbsp;&nbsp;&nbsp; + D:\eclipse<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + configuration<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+ org.eclipse.osgi<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + manifests<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - eclipseme_0.1.0.MF<BR>例2:<BR>&nbsp;&nbsp;&nbsp; + D:\eclipse<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + plugins<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + org.eclipse.osgi_3.0.0<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + META-INF<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - MANIFEST.MF<BR>在Eclipse3.0中,插件也可被称为Bundle.Bundle的类文件和资源文件就是插件文件夹下的JAR文件和其他资源文件,Bundle的MANIFEST文件就是上文中提到的MF文件.<BR>Eclipse的插件信息是被配置在plugin.xml中的.OSGi Bundle信息是被配置在MANIFEST.MF文件中的.下面就说说它们的联系.<BR>plugin.xml包括三个部分的信息.<BR>1&gt;&nbsp;&nbsp;&nbsp;&nbsp; 插件基本信息.如插件名,插件ID号,插件版本号,插件提供者名和插件类的全限定名.<BR>2&gt;&nbsp;&nbsp;&nbsp;&nbsp; 插件的依赖关系和插件的运行库.<BR>3&gt;&nbsp;&nbsp;&nbsp;&nbsp; 插件的扩展和扩展点.<BR>在Eclipse3.0中,前两部分的信息可以被配置在MANIFEST.MF文件中.如Eclipse3.0中的runtime插件.考虑到与Eclipse以前版本的兼容,plugin.xml文件仍然支持对上三部分信息的配置格式.但是,Eclipse3.0平台运行在处理插件信息时,它认为插件是一个Bundle外加上扩展和扩展点.<BR>Eclipse2.1的平台运行内核缓存所有插件的注册信息在Registry API中,所有这些信息是从.registry文件中或解析所有的plugin.xml文件(安装新插件的情况下)获取的.在Eclipse3.0中,Registry API已经不被建议使用,对所有插件的注册信息的缓存已被重构为两部分,一是Bundle数据,另外是ExtensionRegistry API,它们分别从.bundledata或.state文件和.registry.X文件中获取.这三个文件是Eclipse生成的,它们的数据来源是各个插件的plugin.xml和MANIFEST.MF文件.当平台安装新的插件时,它们都将被重新生成.之所以从它们中而不是直接解析plugin.xml和MANIFEST.MF文件,是要Eclipse起动更快.<BR>在Eclipse3.0中,有些插件文件夹下并没有MANIFEST.MF文件,这是为了兼容Eclipse以前版本的插件.对于每一个已被Eclipse3.0安装(installed)的插件(Bundle),系统都会生成一个MF文件在configuration\org.eclipse.osgi\manifests目录下(已经有MANIFEST.MF文件的插件除外).被生成的MF文件内容只是该插件的plugin.xml文件中扩展点外的部分数据.</P><img src ="http://www.blogjava.net/ultramarine/aggbug/13817.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ultramarine/" target="_blank">ultramarine</a> 2005-09-23 10:57 <a href="http://www.blogjava.net/ultramarine/articles/13817.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ZT:Eclipse插件架构笔记 </title><link>http://www.blogjava.net/ultramarine/articles/13813.html</link><dc:creator>ultramarine</dc:creator><author>ultramarine</author><pubDate>Fri, 23 Sep 2005 02:43:00 GMT</pubDate><guid>http://www.blogjava.net/ultramarine/articles/13813.html</guid><wfw:comment>http://www.blogjava.net/ultramarine/comments/13813.html</wfw:comment><comments>http://www.blogjava.net/ultramarine/articles/13813.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ultramarine/comments/commentRss/13813.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ultramarine/services/trackbacks/13813.html</trackback:ping><description><![CDATA[<!--StartFragment --><SPAN>本文只是一篇翻译</SPAN><SPAN>.</SPAN><SPAN>其原创文章的标题是</SPAN><SPAN>"Notes on the Eclipse Plug-in Architecture",URL</SPAN><SPAN>联接为</SPAN><SPAN><A href="http://www.eclipse.org/articles/Article-Plug-in-architecture/plugin_architecture.html"><SPAN style="COLOR: windowtext; TEXT-DECORATION: none">http://www.eclipse.org/articles/Article-Plug-in-architecture/plugin_architecture.html</SPAN></A>,</SPAN><SPAN>该文剖析了</SPAN><SPAN>Eclipse</SPAN><SPAN>插件系统的结构</SPAN><SPAN>,</SPAN><SPAN>为渴望了解</SPAN><SPAN>Eclipse</SPAN><SPAN>插件的程序员提供了有益的指导</SPAN><SPAN>.</SPAN><SPAN>希望我的这篇翻译能对大家理解该文有些帮助</SPAN><BR>Eclipse插件架构笔记<BR>概要<BR>为建立组件级的应用,Eclipse插件系统包含了一个架构模式.本文以参与者和协作者的角色来介绍这一架构模式,目的是提供对插件的理解,插件是怎样被定义和处理的,以及使用Eclipse工作平台来独立生产插件的机制.<BR>Azad Bolour, Bolour Computing <BR>July 3, 2003 <BR><BR>内容列表<BR><U>1.</U>简介<BR><U>2.</U>Eclispe插件模型<BR><U>3.</U>扩展处理<BR>4.一个可扩展的算术函数服务实例<BR><U>5.</U>监听器扩展和观察者模式<BR><U>6.</U>摘要和总结<BR><BR><A name=1.>1.简介<BR>Eclipse是一个可扩展的IDE平台.为了控制工具组协同工作以支持程序任务,它提供了一个核心服务.工具建立者可以把他们的,被称为<EM>Eclipse</EM> <EM>plug-in</EM>的,并符合Eclipse插件规范的可插组件封装进Eclipse平台中.Eclipse的一个基本的可扩展机制是,新插件可以添加处理元素到已存在的插件中,Eclispe也提供一组核心插件来启动这一处理.<BR>尽管Eclipse是个IDE平台,但是它的思想和组织架构的核心是支持一个通用模型,该模型可为多个开发者建立组件级的应用.对Eclipse中的这一系统组件的通用模型的内容将在本文的软件模式部分中描述.本文旨在为新插件开发者,如需要全面理解插件模型(像插件怎样工作的,怎样让插件协同工作)的开发者.<BR>本文的结构如下.第二部分略述了Eclipse插件模型和插件的声明性规范以及他们在这一模型中的关系.第三部分解释了插件开发者必须做什么才能允许他们的插件生效.第四部分提供了一个完整的插件例子.第五部分比较了Eclipse插件模型和相对简单的观察者模式.第六部分概述了 Eclipse插件中的主要架构思想以总结本文.<BR>本文并不涉及用户使用Eclipse插件开发环境(PDE)来建立和测试插件.关于这方面的内容请参照其它的在线文档.<BR></A><A name=2.>2. Eclipse插件模型<BR>Eclipse 插件是一个在Eclipse工作平台中提供某些服务类型的组件.这个组件就是一个可以在系统部署期间被配置到系统中的对象.Eclipse运行组件提供了支持一组在无缝环境中进行开发活动以协同工作的插件激活和操作的基础设施.简单地说,在一个Eclipse运行实例中,一个插件是被包含在某些插件运行类或插件类的实例中.插件类为插件实例提供了配置和管理支持.Eclipse中的插件类必须继承<EM>org.eclipse.core.runtime.Plugin</EM>类.它是一个为管理插件而提供有通用工具的抽象类.<BR>Eclipse安装目录包含有部署有单个插件的插件文件夹.在插件文件夹下,每一个插件又被安装在它自己的文件夹下.插件被描述在一个XML清单文件中,称为plugin.xml,它被放在插件文件夹下.这个清单文件告诉Eclipse运行组件它需要激活该插件的信息.<BR>插件清单文件的解析内容可编程地存储在<EM>plug-in registry API</EM>中.被解析的插件定义被缓存在称为<EM>plug-in registry</EM>的内存容器中.通过使用plug-in registry API, Eclipse运行组件实例化每一个插件实例. plug-in registry API也被自己的插件代码用来获取插件信息.<BR>这是一个最小的插件清单文件:<BR>
<TABLE cellPadding=0 width=350 border=0>
<TBODY>
<TR>
<TD><?xml version="1.0" encoding="UTF-8"?><BR><PLUGIN<BR>&nbsp; name="JUnit Testing Framework"<BR>&nbsp; id="org.junit"<BR>&nbsp; version="3.7"<BR>&nbsp; provider-name="Eclipse.org"&gt;<BR>&nbsp; <RUNTIME><BR>&nbsp;&nbsp;&nbsp; <LIBRARY name="junit.jar"><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <EXPORT name="*" /><BR>&nbsp;&nbsp;&nbsp; </LIBRARY><BR>&nbsp; </RUNTIME><BR></PLUGIN><BR>&nbsp;&nbsp;&nbsp;&nbsp; Listing 2.1. A Minimal Plug-in Manifest File. <BR></TD></TR></TBODY></TABLE>这个清单文件描述了Eclipse工作平台中的JUnit测试框架服务.(注意:为了增强可读性,这个清单文件的内容是在本文的英文本地化环境中被复制的)<BR>Eclipse平台插件清单规范文档化了在定义插件中用到的XML元素和属性.(该规范可以在Eclipse平台的帮助文档中找到.)<BR>这里,本文并不关注插件清单文件的内容,插件的唯一标识符(XML属性id)除外.插件标识符被用来引用清单文件中的,或其他相关的插件.插件标识符也可以用来在自己的插件代码中访问插件的运行实例.例如:<BR>&nbsp;&nbsp;&nbsp; Plugin p = Platform.getPlugin(pluginID);<BR>Eclipse运行组件管理插件实例,插件实例可以像如上方式被Eclipse平台使用.插件实例不能被应用程序构建.<BR>2.1. 插件部署和激活<BR>在Eclipse中部署一个插件就是,把插件文件资源(清单文件,jar文件及其他资源)拷贝到Eclipse插件目录下.这个插件就可以在它需要起作用的时候被Eclipse运行组件激活.插件激活意味着导入,实例化和初始化插件运行类.<BR>插件类的主要作用是,在插件激活和钝化等活动中进行专门处理以分配和释放资源.像上述的JUnit插件例子,插件设计者没有对该插件特别指定激活和钝化处理,也没有指定插件类.在这种情况下,Eclipse运行组件将为该插件自动提供一个缺省的插件实例.<BR>当插件需要进行激活和钝化的时候,插件设计者子类化org.eclipse.core.runtime.Plugin类,并覆盖该类的激活和钝化方法,它们是<EM>startup</EM>和<EM>shutdown</EM>方法,同时在相应的插件清单文件(plugin.xml)中,添加该插件子类的全限定名到相应的属性值中.<BR>Eclipse 包含一个被称为Eclipse平台或Eclipse运行以及某些核心插件的插件管理内核.这些核心插件的标识被注册到Eclipse平台中,这样平台就知道在每一个Eclipse的运行实例中激活这些插件.另外,对于哪些非核心插件,当他们在被其他插件需要时被激活.<BR>在Eclipse模型中,插件之间可能存在如下关系:<BR>·&nbsp;&nbsp;&nbsp; <EM>依赖</EM>. 处于这种关系中的是依赖插件和必要条件插件.必要条件插件支持依赖插件的功能.<BR>·&nbsp;&nbsp;&nbsp; <EM>扩展</EM><EM> </EM>处于这种关系中的是宿主插件和继承者插件.继承者插件继承宿主插件的功能.<BR>这些关系被声明在插件清单XML文件的requires和extension属性中(细节将在下面的部分中讨论).<BR>对于一个已经被部署到Eclipse中的非核心插件,如果它通过依赖和扩展关系的组合来主动关联到核心插件中,就可以被一个Eclipse运行实例激活.当这个插件的功能被要求支持或扩展另一个插件的功能时,它就被激活了.对于一个任何核心插件通过依赖和扩展关系都不可到达的已部署插件,从插件激活的角度来看,它是没有被部署的.当然,如果没有用户动作或其它触发事件的情况下,即使对于一个可到达的插件,在Eclipse运行实例的一段或整个生命周期中,都会保持非激活状态.<BR>2.2. 依赖关系<BR>当一个插件依赖于其它插件的功能的时候,依赖关系就会通过清单文件中的requires元素来指定.如下例:<BR>
<TABLE cellPadding=0 width=350 border=0>
<TBODY>
<TR>
<TD><?xml version="1.0" encoding="UTF-8"?><BR><PLUGIN<BR>&nbsp;&nbsp; id="com.bolour.sample.eclipse.demo"<BR>&nbsp;&nbsp; name="Extension Processing Demo"<BR>&nbsp;&nbsp; version="1.0.0"&gt;<BR>&nbsp;&nbsp; <RUNTIME><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <LIBRARY name="demo.jar" /><BR>&nbsp;&nbsp; </RUNTIME><BR>&nbsp;&nbsp; <REQUIRES><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp; </REQUIRES><BR></PLUGIN><BR>&nbsp;&nbsp;&nbsp;&nbsp; Listing 2.2. Specifying Plug-in Dependencies. <BR></TD></TR></TBODY></TABLE>
<DIV class=entity>
<DIV class=diaryContent id=diary792876 style="DISPLAY: block">
<P>在这个例子中,com.bolour.sample.eclipse.demo类被声明成依赖于(或使用) org.eclipse.ui类.<BR>被定义在清单文件中的依赖关系是一个运行和编译时指令.在运行时,Eclipse必须在依赖插件被激活的时候确认必要条件插件对依赖插件可用.在编译时,Eclipse可以把编译依赖插件所需要的所有必要的插件的jar文件扩充到类路径中.</P></A>
<P>(未完待续)</P></DIV></DIV>
<DIV class=entity><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT>&nbsp;</DIV><img src ="http://www.blogjava.net/ultramarine/aggbug/13813.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ultramarine/" target="_blank">ultramarine</a> 2005-09-23 10:43 <a href="http://www.blogjava.net/ultramarine/articles/13813.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>