作者: Anders小明
什么是企業(yè)應(yīng)用下的業(yè)務(wù)組件
首先,這是一個(gè)組件,這意味著它需要在容器里運(yùn)行,因此不包括任何中間件服務(wù),同時(shí)以一定結(jié)構(gòu)(文件結(jié)構(gòu)或者壓縮格式)組成,被容器識(shí)別;其次,這是一個(gè)業(yè)務(wù)組件,即提供的是應(yīng)用服務(wù),而非技術(shù)服務(wù);第三,這是企業(yè)應(yīng)用,在業(yè)務(wù)上包括功能和服務(wù)(Service,當(dāng)前最時(shí)髦的說(shuō)法,你可以理解為API),技術(shù)上(以J2EE來(lái)講)包括:UI資源(JSF、JSP、JS和CSS等)、應(yīng)用程序(Java)資源和配置文件、數(shù)據(jù)庫(kù)表定義、初始化數(shù)據(jù)和存儲(chǔ)過(guò)程。
為什么要企業(yè)應(yīng)用下的業(yè)務(wù)組件
組件技術(shù)從提出到現(xiàn)在已經(jīng)有20多年了,為什么要提企業(yè)應(yīng)用業(yè)務(wù)組件?因?yàn)楝F(xiàn)有的組件技術(shù)不支持企業(yè)應(yīng)用環(huán)境下的組件要求,J2EE的EJB不支持,.NET的DLL也不支持。
如前所述,一個(gè)企業(yè)應(yīng)用通常包括了交互界面、應(yīng)用代碼以及數(shù)據(jù)庫(kù)結(jié)構(gòu),而不論是EJB還是DLL只支持應(yīng)用代碼,都不包括交互界面和數(shù)據(jù)庫(kù)結(jié)構(gòu)。
如果說(shuō)EJB不是,那么J2EE的EAR或者WAR是否算是一個(gè)組件?答案也不是,EAR或者WAR部署的是一個(gè)企業(yè)應(yīng)用,請(qǐng)注意EJB規(guī)范中明確說(shuō):The Enterprise JavaBeans architecture is a architecture for the development and deployment of component-based (distributed) business applications(EJB 2.x和3.x唯一的區(qū)別是2.x有distributed),它們有自己的應(yīng)用域,彼此相互隔離(簡(jiǎn)單的看,它們有各自獨(dú)立的會(huì)話管理)。.NET也是有自己的應(yīng)用域概念。
更進(jìn)一步,基于應(yīng)用的部署導(dǎo)致了三個(gè)隔離問題:交互(界面)隔離、程序訪問隔離和數(shù)據(jù)隔離(請(qǐng)注意這三個(gè)問題分別對(duì)應(yīng)了企業(yè)應(yīng)用業(yè)務(wù)組件的三個(gè)技術(shù)內(nèi)容)。交互隔離導(dǎo)致了企業(yè)用戶必須訪問不同界面,代碼訪問隔離導(dǎo)致了點(diǎn)對(duì)點(diǎn)的集成以及諸如性能、事務(wù)和異步處理等各種非功能性問題,而數(shù)據(jù)隔離導(dǎo)致了數(shù)據(jù)有效性、一致性等等問題。所有這些都進(jìn)而導(dǎo)致了維護(hù)的問題。
為了解決這些問題,大廠商們都提出了各種解決方案:Portal來(lái)解決交互隔離問題,通過(guò)ESB來(lái)解決代碼訪問隔離問題,以及通過(guò)所謂的信息服務(wù)(Information Service)來(lái)解決數(shù)據(jù)隔離問題。
那么OSGi技術(shù)或者SCA技術(shù)能否滿足要求?答案是目前不能,OSGi最初開發(fā)的目的就不是為了企業(yè)應(yīng)用,只是這幾年開始成熟,并向企業(yè)應(yīng)用方向發(fā)展。09年推出的企業(yè)版(草案)剛剛提出針對(duì)程序訪問問題的方案,如遠(yuǎn)程服務(wù)、事務(wù)管理等;交互隔離問題上規(guī)范并沒有提出相應(yīng)方案,只有Eclipse的Equinox提出了界面的擴(kuò)展點(diǎn)機(jī)制,但這也不能解決B/S環(huán)境的問題;而數(shù)據(jù)隔離問題就沒有任何方案。SCA從一開始就是面向企業(yè)應(yīng)用,不過(guò)不解決交互隔離和數(shù)據(jù)隔離問題。
此外,對(duì)于行業(yè)ISV來(lái)說(shuō),除企業(yè)用戶面臨的這些種種問題,還面臨著其它問題。企業(yè)用戶畢竟只是面對(duì)自己的需求,行業(yè)ISV卻面臨著多個(gè)企業(yè)用戶的需求,面臨定制化帶來(lái)的維護(hù)問題,特別是業(yè)務(wù)和技術(shù)的隔離問題(即如何保持構(gòu)建業(yè)務(wù)組件的所使用技術(shù)的平穩(wěn)升級(jí))。
組件的容器
既然要企業(yè)應(yīng)用下的業(yè)務(wù)組件,而現(xiàn)有的組件技術(shù)又無(wú)法支撐,那么就需要一個(gè)新的組件容器了(當(dāng)然,作為一個(gè)普通開發(fā)人員,我們無(wú)法新建一個(gè)公開標(biāo)準(zhǔn)的組件體系,也獨(dú)立維護(hù)一個(gè)私有的)。新的組件容器完全使用現(xiàn)有的中間件技術(shù),并加上一些新的內(nèi)容,包括如下:
- 組件框架,識(shí)別組件,以及組件(文件)結(jié)構(gòu)和各個(gè)技術(shù)工件。
- 技術(shù)框架,提供業(yè)務(wù)無(wú)關(guān)的技術(shù)支持,以便于技術(shù)的平穩(wěn)升級(jí)切換。
- 運(yùn)行容器,采用現(xiàn)有中間件技術(shù),包括Tomcat、應(yīng)用服務(wù)器和數(shù)據(jù)庫(kù)服務(wù)等;
- 工具,包括打包以及部署工具等。
關(guān)于數(shù)據(jù)隔離問題,在EIP中提到了各種解決方案,這里采用的共享數(shù)據(jù)庫(kù)方式,即各個(gè)組件都共用一個(gè)數(shù)據(jù)庫(kù),各個(gè)組件只提供數(shù)據(jù)庫(kù)定義和初時(shí)數(shù)據(jù)(如同EJB/OSGi一樣,運(yùn)行時(shí)環(huán)境由容器提供)。
組件的關(guān)系
組件的關(guān)系分為兩種:依賴和聯(lián)動(dòng)。依賴關(guān)系在已有的組件技術(shù)上已經(jīng)廣為認(rèn)知,而聯(lián)動(dòng)則是新創(chuàng)造的(肯定不是第一個(gè)創(chuàng)建的,只不過(guò)不同人有不同的叫法)。
聯(lián)動(dòng)和依賴的區(qū)別是:如果有組件B和組件A聯(lián)動(dòng),則組件B可以在沒有組件A的情況下運(yùn)行,并提供相應(yīng)功能。
針對(duì)三種不同技術(shù)工件(即三個(gè)隔離問題)呈現(xiàn)不同特點(diǎn),如下:
1. UI資源(交互隔離問題),依賴是指UI資源的嵌入、引用和替換,聯(lián)動(dòng)是指UI資源的新增。
2. 應(yīng)用程序(程序訪問隔離),依賴是指API/模型依賴,聯(lián)動(dòng)是指消息(傳統(tǒng)消息和JMS消息)以及SPI實(shí)現(xiàn)。其中,無(wú)論是依賴或者聯(lián)動(dòng)都涉及到相應(yīng)的非功能性需求,包括:異步、事務(wù)控制和服務(wù)時(shí)限等。
3. 數(shù)據(jù)庫(kù)資源(數(shù)據(jù)隔離),依賴是指外鍵關(guān)聯(lián)和級(jí)聯(lián)操作,無(wú)明顯的聯(lián)動(dòng)關(guān)系。
這里,需要關(guān)注應(yīng)用程序的依賴和聯(lián)動(dòng)
1. SPI和API存在業(yè)務(wù)不匹配問題。
雖然組件A依賴組件B,但是不代表組件B提供的服務(wù)完全匹配組件A的要求。有時(shí)組件A所需要的數(shù)據(jù)需要組件B的多個(gè)API組成,為了開發(fā)方便或者組件A所需要的性能問題,可能會(huì)在組件B新寫一個(gè)接口給組件A使用,注意該接口不是組件B的API,該接口僅適用于組件A。
2. 盡可能的使用SPI集成方式
SPI集成方式是相對(duì)于API集成方式,API集成方式就是,組件B直接調(diào)用其它組件的API及其模型。SPI集成方式(類似于依賴倒置),組件B定義其所需要的接口及其模型,由組件A或者膠水層代碼來(lái)實(shí)現(xiàn)。
這個(gè)點(diǎn)對(duì)于行業(yè)ISV尤為明顯。對(duì)于企業(yè)用戶來(lái)說(shuō),依賴是明確的,組件A依賴/聯(lián)動(dòng)于組件B,但對(duì)于行業(yè)ISV,則面臨著定制化問題,雖然組件A依賴/聯(lián)動(dòng)于組件B,但是在某個(gè)定制化項(xiàng)目中,由于客戶已有系統(tǒng)C,而需要組件A依賴/聯(lián)動(dòng)于客戶已有系統(tǒng)C。此時(shí)采用SPI方式。
在開源世界里采用SPI方式更是廣泛。很多框架為了兼容(同一功能)不同實(shí)現(xiàn)的類庫(kù),都是先定義框架所需接口,并同時(shí)提供不同類庫(kù)的膠水代碼。
不論是EJB/OSGi/SCA都沒有對(duì)SPI集成方式的支持。
3. 依賴和聯(lián)動(dòng)的非功能性需求。
事實(shí)上,非功能性需求都是在集成時(shí)才存在的。以事務(wù)管理為例,除了及其少數(shù)的例子外,大部分事務(wù)只能在處理流程才被決定(注意,EJB在這方面著是定義在API上的,這樣的設(shè)計(jì)是不適應(yīng)需求的),而組件A的API在用例1中需要被異步調(diào)用,而在用例2中需要被同步調(diào)用是常見的。即便是OSGi規(guī)范,也在這方面沒有任何處理。
組件的定制化
定制化問題只針對(duì)于行業(yè)ISV有效,對(duì)于企業(yè)用戶來(lái)說(shuō),除非是那種跨國(guó)企業(yè)在面臨不同國(guó)度的業(yè)務(wù)模式、法律監(jiān)管和會(huì)計(jì)制度等差異,存在定制化需要,即使如此,ISV和企業(yè)用戶對(duì)于同一問題的解決方式也是不同的。
既然我們已經(jīng)將原有的應(yīng)用采用組件化方式開發(fā),那么應(yīng)用的定制化問題就轉(zhuǎn)化為組件的定制化問題。同樣,應(yīng)用的定制化手段也就轉(zhuǎn)化為組件的定制化手段。
組件框架
羅羅嗦嗦的說(shuō)了半天,有人就說(shuō)了:這不就是把UI、Java和數(shù)據(jù)庫(kù)三個(gè)東東一打包,然后說(shuō)這就是一個(gè)企業(yè)應(yīng)用下的業(yè)務(wù)組件,有啥新意呢,不就是模塊化開發(fā)嘛,一直一來(lái)大家都是就是這么搞的嘛,何必搞個(gè)怪名詞來(lái)忽悠。
是的,就是把UI、Java和數(shù)據(jù)庫(kù)三個(gè)東東整合在一起,組件容器說(shuō)提到的技術(shù)框架很多的開發(fā)隊(duì)伍都有一套,運(yùn)行容器更是有無(wú)數(shù)開源商業(yè)的,打包部署工具更是寫了無(wú)數(shù)。
這確確實(shí)實(shí)就是我們常說(shuō)的模塊化開發(fā)。但是模塊化開發(fā)不同于組件開發(fā),模塊化開發(fā)只是在邏輯上做了切分,物理上(開發(fā)出的系統(tǒng)代碼)通常并沒有真正意義上的隔離,一切都只是在文檔中。
我們需要一點(diǎn)干貨,只有實(shí)實(shí)在在的組件框架才能組件化開發(fā)真正落地的(如同OSGi框架那樣):我們需要一個(gè)類似于Equinox的界面擴(kuò)展框架來(lái)支持UI資源的依賴和聯(lián)動(dòng);我們需要一個(gè)集成框架來(lái)支持應(yīng)用程序的依賴和聯(lián)動(dòng),解決所面臨的種種問題(業(yè)務(wù)不匹配、SPI集成以及各種非功能性需求);我們需要一個(gè)打包部署工具(類似Spring DM)提供部署UI資源、應(yīng)用程序和數(shù)據(jù)庫(kù)定義資源(Spring DM提供了基于Web資源的部署能力)。
其它問題
對(duì)于采用J2EE下B/S環(huán)境的組件應(yīng)用還面臨一個(gè)問題,即現(xiàn)有Servlet規(guī)范只允許一個(gè)web.xml,不支持組件各自定義私有的Filter和Servlet,不過(guò)這個(gè)問題不是很嚴(yán)重,在現(xiàn)有技術(shù)框架已經(jīng)支持一份簡(jiǎn)單的web.xml,而新的Servlet規(guī)范已經(jīng)允許多個(gè)web.xml。
分布式部署以及集群部署問題,這其實(shí)不是個(gè)問題。基于應(yīng)用的我們有很多手段和技術(shù),那么基于組件的也一樣有辦法。