之前也寫過關(guān)于Service-Oriented Component Model的blog了,Service-Oriented Component Model(以下簡稱SOCM)是OSGi R4中最為重要的改進,SOCM也是切實體現(xiàn)OSGi的動態(tài)性的模型,大家在使用SOCM的時候可能會因為受到原有思想的影響而一時無法理解,在這篇blog中將再次的對SOCM進行講解,以便大家能夠更好的理解和進行運用。
SOCM是一種模塊化的詳細設(shè)計思想,不屬于架構(gòu)級別的思想,相應(yīng)的我們對比一下傳統(tǒng)情況下基于Spring的模塊化詳細設(shè)計,在Spring中,對于一個模塊的詳細設(shè)計,通常可以這么來簡述,模塊由多個bean共同構(gòu)成,bean通過注入其他bean實現(xiàn)的接口來獲取相應(yīng)的功能,同樣通過實現(xiàn)接口來對外提供功能(加上xml中的描述),在系統(tǒng)啟動時默認情況下所有的bean都自動的初始化了,當(dāng)然,也可以通過類似lazy的屬性使得bean延遲的進行加載,在bean啟動后其依賴關(guān)系就已經(jīng)確定,是一種靜態(tài)的依賴關(guān)系,bean的生命周期可通過spring提供的接口來進行管理。
通常來講習(xí)慣了基于spring實現(xiàn)的同學(xué)們在轉(zhuǎn)變到使用SOCM時會碰到一些問題:
1、怎么樣注入其他Component?
????? 這個思想呢,我個人覺得是在使用spring時本來就有些錯誤了,注入思想最重要的就是接口注入,所以在說注入其他Component這句話上是有一定的概念性的錯誤的,每個Component其實都是通過set接口來獲得相應(yīng)接口的功能,按照SOCM的說法,就是每個Component通過bind相應(yīng)的服務(wù)的接口來獲取需要使用的功能。
????? 在SOCM中,要引用其他的Service非常的簡單,和Spring的DI沒有很大的區(qū)別,也可以通過setService這樣的方法來實現(xiàn),和spring的不同只是spring在設(shè)置bean的依賴時是通過ref bean="beanID"來獲取,而SOCM中呢,則是充分的Service-Oriented的表達方式:
????? <reference name="LogService" interface="org.osgi.service.log.LogService" bind="setLog" unbind="unsetLog" policy="dynamic"/>
??????通過的是interface屬性來獲取到所需的服務(wù),而不是通過ref bean的那種方式,這里也是充分表達SOCM是一種動態(tài)化設(shè)計的思想。
2、怎么樣管理Component的生命周期?
?????? 這是大家最為迷惑的,當(dāng)你查遍OSGi的相關(guān)文檔后,會發(fā)現(xiàn)OSGi是沒有提供接口來外部調(diào)用Component的呢,這和Spring提供了接口調(diào)用bean完全不同,在SOCM中Component的生命周期是由OSGi框架來負責(zé)管理的,外部沒法通過接口去調(diào)用某個Component,這就會使大家產(chǎn)生疑問,那么Component中的方法是怎么被執(zhí)行的呢,對于這個疑問,需要分成兩種形式的Component來看待:
?????? (1)、只引用其他Service的Component;
????????????????對于這種類型的Component,在啟動Bundle后OSGi將會自動的對Component進行激活,Component激活的前提是Component所引用的Service滿足條件,Component激活時將會通過調(diào)用bind屬性對應(yīng)的方法將相應(yīng)的服務(wù)注入,在將所需的服務(wù)均注入后,將會調(diào)用Component中的activate方法,如沒有此方法,則不進行調(diào)用,:),在這種情況下,我們會發(fā)現(xiàn)以前Bundle中的BundleActivator通常都會變得沒有意義,完全可以通過編寫一個POJO的Component來實現(xiàn)同樣的功能和效果,而且更為簡單。
?????????????? 對于這種Component,我們現(xiàn)在可以清楚,只要Component所必須需要的服務(wù)都存在,那么它就會被自動的激活,這種Component的例子可以參見OSGi Opendoc所附帶的ds部分代碼中的LoginServlet。
?????? (2)、對外提供Service的Component;
???????????????如果Component對外提供了Service,那么只有當(dāng)這個service需要被使用時Component才會被激活,這是它區(qū)別于第一種形式Component的地方。
?????????????? 對于這種Component,可以參見OSGi Opendoc所附帶的ds部分代碼中的DBValidatorImpl(如果你想看它是什么時候被激活的話,可以增加一個activate(ComponentContext context)方法來確定)。
??????? 其實對于上面兩種形式Component的激活原理,我們從設(shè)計角度去看的話很容易理解,第一種Component相當(dāng)于消費型的,這種Component自然是直接就需要啟動了,而對于第二種呢,是提供服務(wù)型的,當(dāng)沒人需要服務(wù)的時候,自然沒必要激活了。
?????? 為什么Component的生命周期需要交給OSGi框架去管理,而不能通過外部管理呢,這就是OSGi動態(tài)性特征的表現(xiàn),Component什么時候能激活取決于系統(tǒng)運行時的狀況,這和靜態(tài)的設(shè)計思想是完全不同,例如當(dāng)Component所必須的服務(wù)在系統(tǒng)中突然不存在了時,這個時候Component將會變成不激活的狀態(tài),這和傳統(tǒng)的靜態(tài)化的bean有很大的不同,Component的狀態(tài)是會根據(jù)運行時的情況來動態(tài)改變的,這自然是遠強于靜態(tài)化的bean的系統(tǒng)了。
其實從上面的問題可以看出,當(dāng)你將基于Spring的模塊移植到OSGi中時,我相信你的系統(tǒng)的設(shè)計會隨著使用SOCM而得到明顯的提升,真正的做到面向服務(wù)、面向接口,SOCM本身就是一種很好的SOA的實現(xiàn)模型,在理解SOCM時,最重要的主要是要把握SOCM的三個核心思想:
1、模塊是由一堆Component組成的;
2、Component通過注入服務(wù)接口和提供服務(wù)接口來實現(xiàn)Component之間的依賴設(shè)定,服務(wù)接口是Component之間依賴的橋梁;
3、Component的生命周期是由OSGi框架管理的。
其實上面仍然只是簡要的講了講SOCM,SOCM在動態(tài)化的表現(xiàn)上其實還有更多的東西,象cardinality、policy、filter等等。
OSGi中實現(xiàn)SOCM的是Declarative Services,不能說SOCM就沒有缺點了,SOCM沒有提供調(diào)用Component的接口(準確的說應(yīng)該是外部調(diào)用SOCM中的Service,例如要在普通的java object中調(diào)用SOCM中的service,目前是沒辦法的,只能把那個java object也作為Component才行),這也就使得系統(tǒng)必須完全遵循SOCM而構(gòu)建,這使得基于SOCM而構(gòu)建的模塊很難與本地的程序做集成,這是它的一個缺點,但是這里面確實有個問題,就是OSGi的Component是動態(tài)化的,其實它是無法簡單的通過提供一個接口來對外部的程序提供SOCM中的service的,必須同時還附帶一個通知模型,以便在service狀態(tài)發(fā)生改變時外部的程序能夠得知,從而做出相應(yīng)的動作,這個問題在SCA中是得到解決了的,EEG對這個問題也表示了關(guān)注,可以相信在不久的將來SOCM將會更加的完善和實用。
ps:之前看EclipseCon 2007中OSGi Long Talks的時候看到Bea的microServices也是基于OSGi的,:),果然沒有出乎意料,也就是說BEA的所有軟件產(chǎn)品將全部基于OSGi了,這對于OSGi的推進無疑是個很好的消息,呵呵,看來IBM的動作還得加快。
另外說說最近Equinox的一個最好的消息,那就是它的基于aspect實現(xiàn)AOP的bundle已經(jīng)推出,:),可以想想這意味著什么,意味著面臨的很多企業(yè)應(yīng)用的問題就得以解決了,象跨Bundle的事務(wù)等等..