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