??xml version="1.0" encoding="utf-8" standalone="yes"?>
]]>
]]>
]]>
]]>
1、部|不是很方便
equinox默认提供的是一个console端的插g部v理Q部|v来需要通过"install reference:file://"q样的方式来安装插gQ不是特别的方便?BR> ^_^Q由于我当时使用的时候equinoxq没提供osgi中httpservice的实玎ͼ便用了oscar中提供的httpservice的实玎ͼZq个httpservice的实现写了一个web端的插g理的工P呵呵Q将来整理后会将q个bundle公布出来Q到时大家直接下载就可以用了?BR> 在部|方面还有一个不方便的地方就是不能指定插件的启动序Q现在equinox是通过config.ini中来实现插g启动序的控制的Q这个在我的web端的插g理工具中也提供直接Q可直接讑֮插g的启动顺序?BR>2、Classpath的问?BR> q个问题是我在用equinox时比较头疼的一个问题,我在bundle中用了spring IoC containerQ而由于spring中用的不是当前cȝ加蝲器,D在加载配|文件的时候会出错Q只得直接修改了spring中那些部分的代码Q将其改Z用当前类的加载器?BR> 在集成其他一些自己含有classpath的东西的时候也很容易出现这个问题?BR> 虽然从原理上来讲q个是可以理解的Q因为在插g体系l构中每个插仉拥有独立的插件类加蝲器,q个实会对集成的有些东西生媄响,抑或我们应该理解为集成的那些东西在这斚w设计有缺P
3、有利于面向接口~程的执?BR> q个应该说是属于插g体系l构的好处,每个插g可以控制自己对外所暴露的包Q这个时候就可以只暴露接口所在的包,^_^Q呵呵,面向接口的编E就q么被强制的执行了?BR>4、插件开发的IDE
q点是我觉得equinox的天然优势,拥有一个eclipseq么优秀的插件开发的IDEQ^_^
支持了插件的调试...
我认为的最重要的一Ҏ它解决了插g依赖的问题,通常在出现project依赖的时候我们都需要引用该project或是该project生成的jarQ而在插g体系l构中只需要在插g文g中定义所依赖的包卛_Q这个就解决了去引用project那样方式引v整个目工程包乱和开发不便的现象?
5、插件的试
q点我想也是大家很关心的Q不q大家可以放心,基本没什么不同的Qunit testl箋使用Mock方式完成所试的unit的外部依赖的部分Q集成测试则需要启动equinox容器Q这点应该没什么不能接受的?BR>6、Bundle和Service的定?BR> q个是插g体系l构带来的一个挑战,如果准确的定义系l中的bundle和service是很关键的一个问题,q对于发挥插件体pȝ构的bundleU别、serviceU别的重用性至关重要,同时对于整个目l构的清晰度也会产生很大的媄响,形成bundle的清晰的service依赖l构?BR>7、面向服务的体系
我想q也同样是象equinoxq样的插件框架引发用者的思考,pȝ采用的应该是一U面向服务的体系Q服务才是系l的核心Qbundle只是一个管理器而已Q这个时候怎么栯计出动态、松散耦合的服务体pL很关键的?BR>
equinox一直都在发展之中,它的maillist一直就非常的热闹,而且现在对于osgi中的service它基本都实现了,也已l开始提供对于servlet container集成的支持,^_^Q极度支持equinoxQ虽然它q需要不断的努力.....
可以看得出,l过我上面的ȝQ大家其实要担心的是引用一U新的体pȝ构带来的设计层面的变革,而不是开发实现层面,^_^
OSGI
Eclipse 3.0后采用的是OSGI来作为其Plugin Architecture实现的依据,鉴于此就得简单提提OSGI了,主要从Plugin的角度来分析OSGIQOSGI概念中主要分ZBundle和ServiceQ可以认为Bundle是一个模块的理器,主要是通过BundleActivator理模块的生命周期,而Service则是q个模块可暴露对外的服务对象Q这里体COSGI和传l的Plugin Framework不同的一个地方,理和静态结构分开Q在OSGI中通过在manifest.mf文g中增加一些内Ҏ发布BundleQ在其中描述了Bundle的提供商、版本、唯一ID、classpath、暴露对外的包、所依赖的包Q每个Bundle拥有自己的ClassLoader以及contextQ通过context可进行服务的注册、卸载等Q这些操作都会通过事g机制q播l相应的其他的BundleQ一般来说都为通过在Bundle中编写初始需要注册的服务的方法来完成Bundle可供外部使用的服务的暴露功能Q如需要调用其他Plugin提供的服务可通过context的getServiceReference先获取Service的句柄,再通过context.getService(ServiceReference)的方法获取Service的实体?/P>
Eclipse Plugin定义
Eclipse中的Plugin的概念ؓ包含一pd服务的模块即Z个Plugin。既然是遵@OSGI的,也就意味着Plugin通常是由Bundle和N多Service共同构成的,在此基础上Eclipse认ؓPlugin之间通常存在两种关系Q一Uؓ依赖Q一Uؓ扩展Q对于依赖可通过OSGI中元描述信息里添加需要引用的Plugin卛_实现Q但扩展在OSGI中是没有定义的,Eclipse采用了一个Extension Point的方式来实现Plugin的扩展功能?BR>l合OSGI
Eclipse遵@OSGI对于Plugin的ID、版本、提供商、classpath、所依赖的plugin以及可暴露对外的包均在manifest.mf文g中定义?BR>Plugin Extension Point
对于扩展QEclipse采用Extension Point的方式来实现Q每个Plugin可定义自qExtension PointQ同时也可实现其他Plugin的Extension PointQ由于这个在OSGI中是未定义的Q在Eclipse中仍焉过在plugin.xml中进行描qͼ描述的方法ؓ通过<extension-point id="" name="" schema="">的Ş式来定义Plugin的扩展点Q通过<extension point="">的Ş式来定义实现的其他Plugin的扩展点Q所提供的扩展点通过schema的方式进行描qͼ详细见eclipse extension-point schema规范Qؓ了更好的说明扩展点这个概念,举例如下Q如工具栏就是工hPlugin提供的一个扩展点Q其他的Plugin可通过此扩展点d按钮臛_h中,q可相应的添加按钮所对应的事?当然Q此事g必须实现工具栏Plugin此扩展点所要求的接?Q工h的Plugin通过callback的方式来相应的响应按钮的动作。可见通过Extension Point的方式可以很好的提供Plugin的扩展方式以及实现扩展的方式?/P>
Eclipse Plugin Framework
那么Eclipse是如何做到Plugin机制的实现的呢?Q还是先讲讲Eclipse的设计风|Eclipse在设计时有个重要的分层法则,卌a层相兛_语言层无关的代码分开(如jdt.core和core)Q核心与UI分开(如workbench.ui和workbench.core)q两个分层法则,q个在Eclipse代码中处处可见,在Plugin Framework部分也充分得体现了这个,遵@OSGIQEclipse首先是实C一个OSGI ImplQ这个主要通过它的FrameWork、BundleHost、ServiceRegistry、BundleContextImpl{对象来实现Q如果关心的话大家可以看看这部分的代码,实现了Bundle的安装、触发、卸载以及Service的注册、卸载、调用,在Plugin机制上Eclipse采用的ؓlazy load的方式,卛_调用时才q行实际的启动,采用的ؓ句柄/实体的方式来实现Q外部则通过OSGIq行启动、停止等动作Q各Plugin则通过BundleContext来进行服务的注册、卸载和调用Q这是OSGI的部分实现的单介l?BR>那么Extension Point斚wEclipse是如何实现的呢,在加载PluginӞEclipse通过对plugin.xml的解析获取其中的<extension-point>节点?lt;extension>节点Qƈ相应的注册到ExtensionRegistry中,而各个提供扩展点的Plugin在提供扩展点的地方进行处理,如工hPlugin提供了工h的扩展点Q那么在构成工具栏时Plugin通过Platform.getPluginRegistry().getExtensionPoint(扩展点ID)的方法获取所有实现此扩展点的集合IExtensionPoint[]Q通过此集合可获取IConfigurationElement[]Q而通过q个可以获?lt;extension point="">其中的配|,同时q可通过IConfigurationElement创徏回调对象的实例,通过q样的方法Eclipse也就实现了对于Plugin的扩展以及扩展的功能的回调。在Plugin Framework中还涉及很多事g机制的用,比如Framework的事件机Ӟ以便在Bundle注册、Service注册的时候进行通知?/P>
ȝ
通过对Eclipse启动q程的分析,可清晰的看到Eclipse Kernel+Core Plugins+Application Plugins的方式,在代码中分别对应为loadBasicBundles和registerApplicationServicesQloadBasicBundles通过加蝲config.ini中的osgi.bundles完成基本的bundles的加载,ȝ看这个配|会发现是org.eclipse.core.runtimeq有一个updateQcore.runtime又会通过IDEApplication来完成整个Eclipse的启动,同时会注册所有与workbench相关的plugin?BR>Eclipse׃以前版本的Plugin Framework是没有采用OSGI的,所以通过EclipseAdaptor的方式来实现与以往的兼容,目前新的Plugin采用的方式基本就是manifest.mf描述Plugin OSGI部分的信息,Plugin.xml描述扩展点的信息?BR>Eclipse中有非常多优U的设计,q个在看它的代码时会有很q感触Q比如Contributing to Eclipse中提到的Extension Object/Interface的设计,实是非常的不错Q虽然看C可能觉得很简单,关键是要惛_到ƈ合适的M用?BR>ȝ陈词Q^_^QEclipse Plugin Framework是采用OSGI Impl+Plugin Extension-Point的方式来共同实现的,实现了Plugin的部|Ӏ编写、独立的Classloader和Context、Plugin中Service的注册、Plugin中Service的调用、Plugin的依赖、Plugin的扩展、Plugin生命周期的管理?/P>
带来的思?BR>Eclipse Plugin Framework采用的是OSGI的实玎ͼ一定程度上我们也能看到OSGI的优点,那么JMX+IoC方式的Plugin Framework与其的比较又是在哪些斚w呢?Eclipse Plugin Framework不的地方又在哪里呢Q哪些地方值得改进呢?
看到x即用q么几个字,但真的又有多Y件做C呢,当然Q不可否认的是也有部分的软g实做到
了,而且做的很好Q例如EclipseQ知名的插g式系l,q有象mavenq些都是Q其实portlet container
那些也都是的Q列丑և来还真的有不。插件式pȝ带来的好处很明显Q最大程度的重用Qؓ快速的搭徏
pȝ提供帮助Q潜在的好处在于要求pȝ以插件式的方式进行设计,帮助你更好的做到模块化的划分以及
帮助pȝ辑ֈ良好的封装性?/P>
需?BR>要做Plugin ArchitectureQ首先需要做的是如何考虑PluginQ其实也是需求,要看你是怎么看待一?/P>
Plugin的,认ؓ一个Plugin应该是怎么LQ认为Plugin是怎么栯l装h构成pȝ的,q个时候需?/P>
的是大家从需求的角度来提求,不要从技术角度来提。一个系l既然是按照Plugin的方式搭建出来,
那么首先需要知道的是就是Plugin能提供什么样的功能,q些功能需要什么参敎ͼq是最基本的,其次?/P>
如何ȝ理这个PluginQ包括修改它的配|参敎ͼ对它的生命周期进行管?启动/暂停/停止{?Q这是以
单独的Plugin角度来看Q如果这个Plugin又得调用其他Plugin提供的功能,那么应该怎么dQ考虑了这
些后又会惛_Plugin应该怎么去部|Ӏ怎么去自动升U。从扩展斚w我们又会考虑到那么我要如何去扩展
一个Plugin呢,q也是很关键的。这都只是简单单的提了一些Plugin的需求,归纳上面的需求可以得?/P>
主要的几点就是Plugin的功能的暴露、Plugin的管理、Plugin的调用、Plugin之间的协作、Plugin的部|?/P>
、Plugin的扩展这几个大的斚w?/P>
技术简?/FONT>
现有的可参考的Plugin Architectureq是有比较多的,例如Eclipse、Geronimo、Maven、Pluto{等Q这
些都是做的比较好的插件式的系l,在这里主要讲讲Eclipse如今使用的Osgi和Geronimo所使用的JMX+IoC
方式实现的Plugin ArchitectureQ应该说两者各有千U,重点q是看对于Plugin的需求到底是怎么L
QOsgi规范系l按照Bundle的方法进行组装,每个Bundle下包含了一pd的ServiceQ通过~写Bundle
完成对于Bundle的管?Start、Stop)Q而Service则ؓBundle所能提供对外的功能Q通过MANIFEST.MFq?/P>
个标准的jar包描q文件来描述bundle所能提供的功能以及一些元数据信息Q由于对Osgi研究不深Q也?/P>
能大概的提提q些了,Eclipse?.0以后的版本开始采用OsgiQƈ兼容其原有的Plugin方式Q可以通过?/P>
读Eclipse源码M解关于基于Osgi来实现Plugin Architecture的方式,Eclipse是基本实C上述需?/P>
部分的,不过个h认ؓ在plugin的管理、plugin之间的协作、plugin的部|上q可以加强;接下来提?/P>
JMX+IoC方式Q对JMXE有了解的h都知道JMX被大量的应用服务器所使用Q如Jboss、Tomcat、Weblogic?/P>
WebSphere{等Q数不胜敎ͼJMX的是一个管理概念,对JMX不在此详l的介绍Q但其实它同h一?/P>
Plugin的概念,依照JMXpȝ可以~写MBean的方式来暴露Plugin的功能,q实现对于Plugin的管?各种
方式Qhttp、rmi{等)、Plugin的调用、Plugin的部|Ԍ那么Z么要引入IoC呢,IoC帮助实现Plugin?/P>
间的协作Qƈ且是通过注入的方式来实现QIoC也不在这里详l的LqC?/P>
ȝ
通过对上面两U实现Plugin Architecture的简介,分别都实C需求中的内容,但都有提升的余地Q个
为Osgi的方式需提升对于Plugin理的关?不仅是生命周期管?、而JMX+IoC方式则需提高对于
Plugin内部l构的关?pOsgiPlugin分解ZBundle和Service)Q至于Plugin的扩展方面觉?/P>
Eclipse的Extension Point是非怸错的一个设计,不过同时也看出在Plugin Architecture的实C?/P>
本都采用了管理和静态结构分ȝҎQ其实这个好处是非常明显的,可以快速的系l原有的模块通过
~写一个管理类的方法就可作为plugin攑օpȝ中,q提升了便性,当然最大的作用q是分清了职责,
说一句题外话Q职责单一一直是软g设计的重中之重,此文U属抛砖引玉Q希望能听到更多关于Plugin
Architecture的声韻I也希望大安xPlugin ArchitectureQ最q也Z一个JPFQ不知道大家是否?/P>
所了解?/P>
可快速开发一个插Ӟ量的对现有系l的侵入。在此^C可快速的q行插g的开发,量减少对于pȝ的R入,有良好的开发向导和开?/SPAN>IDE?/SPAN>
可轻杄q行插g的部|Ӏ当开发完毕一个插仉要部|至q_上时Q此步骤应尽量的单?/SPAN>
单的调用其他插g。对于^C其他可用的插件的调用应尽可能的依赖ƈ保持插g的独立性?/SPAN>
单的被调用。其他插件或应用需要调用时应可单的被调用?/SPAN>
可进行测试、调试。可q行单元试、调试,使得开发时更加的简ѝ?/SPAN>
可被扩展。插件可被扩展,方便来可对此插件进行功能上的完善和改进?/SPAN>
可分布式的部|Ԍq支持多U方式调?/SPAN>(Webservice?/SPAN>JMS)。得插件可部v在远端,实现分布式的物理l构?/SPAN>
可自动的升。插件可自动的升U,减小对于插g的维护ƈ保证插g功能的最新?/SPAN>
可被理Q安装、卸载、启用和暂停使用。得用户可Ҏ件进行选择性的配置?/SPAN>
插g异常的管理。保证插件在产生M异常的情况下均可对其q行捕捉q友好的提示用户?/SPAN>
插g日志。在插g的用过E中记录下够的日志Q方便将来对于插件的分析?/SPAN>
产生的数据可被其他插件用。在插g中生的信息数据可被׃nQ得各插g产生的数据可共同构成pȝ的信?BR> |络Q信息得以被׃n?/SPAN> 通常一?/SPAN>Plugin Framework的职责就是:
1?SPAN style="FONT: 7pt 'Times New Roman'">
搜烦相应目录Qƈ目录下可作?/SPAN>Plugin的部分注册到Plugin Framework?/SPAN>2?SPAN style="FONT: 7pt 'Times New Roman'">
提供外部调用Plugin的方?/SPAN>3?SPAN style="FONT: 7pt 'Times New Roman'">
Plugin之间怺交互的方?/SPAN>4?SPAN style="FONT: 7pt 'Times New Roman'">
Plugin的加载,Ҏ其描q构建相应的ClassLoader5?SPAN style="FONT: 7pt 'Times New Roman'">
Plugin的编写说?/SPAN>当然Q一个好?/SPAN>Plugin Framework应该q提?/SPAN>Plugin开发向|Plugin开发、调试、部|的IDE{等
主要希望׃面几Ҏq行讨论Q呵呵,当然Q大家也可以增加一些大家认为值得讨论的部分:
1?SPAN style="FONT: 7pt 'Times New Roman'">
Plugin的编?/SPAN>你构思中一个好?/SPAN>Plugin System会要?/SPAN>Plugin如何~写Q我考虑中一个好?/SPAN>Plugin System?/SPAN>Plugin没有M~码上的要求Q要求的只是其描q文件的~写?/SPAN>
2?SPAN style="FONT: 7pt 'Times New Roman'">
Plugin的部|?/SPAN>Plugin的部|Ԍ如何更加方便的去部v一?/SPAN>PluginQ就?/SPAN>Osgi可以通过|络讉K{等Q考虑中根据配|从相应的目录或|站搜烦Pluginq注册到pȝ?/SPAN>
3?SPAN style="FONT: 7pt 'Times New Roman'">
Plugin的调?/SPAN>对于Plugin的调用,ҎPlugin的描q采取相应的方式调用PluginQ例?/SPAN>webservice方式?/SPAN>socket方式{等
4?SPAN style="FONT: 7pt 'Times New Roman'">
Plugin的交?/SPAN>对于Plugin的交互,也许可以参?/SPAN>Maven的方式,比如需要调用其他的pluginQ则采用cMq样的配|或调用<attain plugin=”pluginname?function=”sendmail?>抑或采用IoC容器注入依赖Q?
5?SPAN style="FONT: 7pt 'Times New Roman'">
Plugin的扩?/SPAN>对于Plugin的扩展,q个Eclipse的扩展点完全值得参?/SPAN>
6?SPAN style="FONT: 7pt 'Times New Roman'">
Plugin的依赖关pȝ分析