OpenCore: OSGi上部署Hibernate的四種方式關(guān)鍵字: osgiOpenCore: OSGi上部署Hibernate的四種方式 OpenCore是在OSGi規(guī)范上構(gòu)建的微內(nèi)核(Microkenerl),基于純組件(Pure Plugin)開放源碼企業(yè)應(yīng)用軟件平臺(tái)。OpenCore數(shù)據(jù)層實(shí)現(xiàn)OSGi上集成Hibernate,Hibernate及其依賴庫作為一個(gè)單獨(dú)的插件,這樣帶來一個(gè)問題,就是OSGi平臺(tái)的插件類加載機(jī)制使得Hibernate無法正確加載分布在不同插件內(nèi)部的模型對(duì)象與O/R映射文件。本文討論四種解決方案:
模型對(duì)象(Domain Objects)集中到獨(dú)立的插件(Bundle)內(nèi),Hibernate插件依賴這些模型對(duì)象插件。這是最簡(jiǎn)單的,也是比較糟糕的方式,比較小的基于OSGi的項(xiàng)目可以這也作做。 依賴方式:業(yè)務(wù)插件------->Hibernate插件 | | | \ \| / |----------- 模型插件 /
把模型對(duì)象插件當(dāng)作Hibernate插件的Fragments,依賴方式如圖:
Equinox(Eclipse提供的OSGi實(shí)現(xiàn))平臺(tái)特有的方式,允許插件(Bundle)聲明自己的伙伴,讓“伙伴插件”來動(dòng)態(tài)加載本插件的類,這也是Hiberate與Equinox集成的官方解決方案。這種方式模型對(duì)象無需部署在單獨(dú)的插件內(nèi),與業(yè)務(wù)插件部署在一起即可,Hibernate插件也無須依賴模型對(duì)象。 具體做法如下: 首先,Hibernate插件(名稱,例如org.opengoss.orm.hibernate)聲明自身可以作為伙伴插件,自描述文件(MANIFEST.MF) 加入描述: Eclipse-BuddyPolicy: registered 然后,模型對(duì)象的業(yè)務(wù)插件中把Hibernate插件加入為伙伴,自描述文件(MANIFEST.MF) 加入描述: Eclipse-RegisterBuddy:org.opengoss.orm.hibernate 具體說明文檔: http://www.ibm.com/developerworks/cn/opensource/os-ecl-osgi/index.html 注意:這種方式無法保證在Hibernate最新版本中應(yīng)用成功。大家可以再試試:)
這是我們目前實(shí)現(xiàn)的方式,通過標(biāo)準(zhǔn)的Eclipse擴(kuò)展點(diǎn)與擴(kuò)展機(jī)制,我們?cè)?/span>Hibernate插件中plugin.xml配置文件中聲明下述擴(kuò)展點(diǎn): <plugin></plugin> <extension-point id="org.opengoss.database.domain.object" name="domainObject"/>
在模型對(duì)象插件中聲明擴(kuò)展,例如: <plugin></plugin> <extension></extension> <extension point="org.opengoss.database.domain.object"> <domainobject></domainobject> <domainObject class="org.opengoss.alarm.core.Alarm"/> </extension>
Hibernate插件的啟動(dòng)中,用代碼配置生成SessionFactory,代碼如下: public void start(BundleContext context) throws Exception { Configuration configuration = new Configuration().configure(new File( "./etc/org.opengoss.database.hibernate/hibernate.cfg.xml")); Class[] domainClasses = getDomainClasses(); for (Class domainClass : domainClasses) { configuration.addClass(domainClass); } sessionFactory = configuration.buildSessionFactory(); Dictionarynew Hashtable props.put("scope", "APPLICATION"); props.put("uid", "Hibernate:SessionFactory"); registration = context.registerService( SessionFactory.class.getName(), sessionFactory, props); } private Class[] getDomainClasses() throws Exception { List<class> domainClasses = </class>new ArrayList<class>();</class> IExtensionPoint point = registry .getExtensionPoint(IConstants.DOMAIN_OBJECT_EXTENSION_POINT); IExtension[] extensions = point.getExtensions(); for (IExtension extension : extensions) { IConfigurationElement[] elements = extension .getConfigurationElements(); for (IConfigurationElement configurationElement : elements) { Bundle bundle = pluginContext.getBundleBySymbolId(extension .getNamespaceIdentifier()); Class domainClass = bundle.loadClass(configurationElement .getAttribute("class")); domainClasses.add(domainClass); } } return domainClasses.toArray(new Class[domainClasses.size()]); } 注意:Hibernate內(nèi)部的類加載機(jī)制實(shí)在無法令人滿意,盡管我們?cè)谶@種方式中已經(jīng)加載所有的模型類對(duì)象,但Hibernate內(nèi)部仍然會(huì)調(diào)用Class.forName()去試圖加載。所以,我們不得不在其自描述文件(MANIFEST.MF) 中加入描述: DynamicImport-Package: * 結(jié)論:我們傾向于第四種方式,由Eclipse的擴(kuò)展點(diǎn)功能來完成這一職責(zé)。不贊成第三種在OSGi規(guī)范層作改進(jìn)的方式,OSGi本身的類加載機(jī)制設(shè)計(jì)非常優(yōu)美,Buddy插件破壞了這種優(yōu)美。 |
|