- 項目實踐精解:基于EJB 3.0和Web Services的Java應用開發
- 李新力 梁立新編著
- 8字
- 2018-12-27 20:23:38
第一部分 整體介紹
第1章 EJB概述
Sun公司正式推出了EJB(Enterprise Java Bean)規范之后,在眾多的公司和開發人員中引起了很大的反響,許多公司都已經推出了或正打算推出EJB產品。EJB已經成為Java技術的研究重點,它是由Sun牽頭、IBM等公司共同參與制定的分布式計算解決方案。其目的主要是為了解決重用組件、商務規則的隱藏等問題,提高軟件開發的可伸縮性,滿足Internet的分布式計算需要。
1.1 EJB的基本概念
EJB是用于開發和部署多層結構的、分布式的、面向對象的Java應用系統的跨平臺的構件體系結構。采用EJB可以使開發商業應用系統變得容易,應用系統可以在一個支持EJB的環境中開發,開發完之后,部署在其他的環境中。隨著需求的改變,應用系統可以不加修改地遷移到其他功能更強、更復雜的服務器上。
1.1.1 為什么要使用EJB
如今開發電子商務平臺已大量使用組件技術,這是因為組件技術提供了服務器上的自治、企業級和分布式功能,并幫助開發者在不同顆粒度級別上定義和封裝系統功能。通過采納組件技術,比傳統程序更易于為日后的需求進行維護、支持和修改。在金融行業中,利用以服務器為中心方式的優勢在于,可以定義商業過程,將其作為一組軟件組件編寫,然后通過多種渠道傳遞。一旦使金融系統變為由單獨的自治組件(而非單一龐大程序)組成,靈活性就隨之而來。
EJB的組件結構是以作為可復用的服務器端組件而設計的,它使企業能夠建立可升級、安全可靠、可運行于多重平臺且以商務為重點的應用程序。EJB可以讓企業開發人員只集中于開發商務邏輯,而不用花費精力去處理分布式服務器端系統所帶來的底層問題,從而使開發人員可以快速開發大規模的企業應用。
使用EJB技術可以使我們獲得以下收益。
1.生產效率
通過使用EJB,企業開發人員將會進一步提高生產效率。他們不僅能夠獲得在Java平臺上的開發成果,而且能夠將注意力集中于商務邏輯,從而使效率倍增。
2.業內支持
試圖建立EJB系統的客戶會獲得一系列可供選擇的解決方案。對于現有的應用系統,許多EJB產品的供應商(例如IBM和BEA)都提供了完善的升級手段,將系統升級到EJB模式。EJB技術已經被越來越多的公司所接受、支持和應用。
3.結構獨立
EJB技術支持“即插即用”的企業級特性。它將開發人員和底層中間件相隔離,開發人員看到的僅僅是J2EE平臺,這樣使得EJB服務器廠商在不干擾用戶的EJB應用程序的前提下,有機會改進中間件層。
4.跨平臺、跨廠商
通過對Java平臺的支持,EJB技術將“僅寫一次,隨處運行”的概念提高到了一個新的水平。它可以保證一個EJB應用程序可運行于任何服務器,只要這個服務器能夠真正提供EJB APIs。
5.EJB組件能提供真正的可重用框架
每一個jar包代表一個EJB組件,一個系統可以由多個可重用的EJB組件構成,例如:樹形結構EJB組件;自增序號EJB組件;用戶資料EJB組件等,這樣的EJB組件可以像積木一樣搭配在大部分應用系統中,提高了系統的開發效率,保證了開發質量。
6.EJB提供了事務機制
事務機制對于一些關鍵事務是很重要的,例如ATM機提款,提款有多個動作:修改數據庫及數錢等,如果這其中有任何一個環節出錯,那么,其他已經實現的操作必須還原,否則,就會出現提款人沒有拿到錢,但是卡上已經扣款等不可思議的事情。
1.2 EJB的體系結構
1.2.1 EJB的基礎結構
容器和服務提供者實現了EJB的基礎構造,這些基礎構造處理了EJB的分布式、事務管理和安全性。EJB規范定義了基礎構造和Java API的各種要求,而沒有去指定用什么技術、平臺和協議來實現他們。
Enterprise Beans,container,server說明了EJB基礎結構的要求,EJB基礎結構必須提供客戶和Enterprise Beans通信的通道。雖然這不是EJB規范所定義的,但保證通道的安全也是很重要的,特別是當客戶通過Internet訪問遠程的Enterprise Beans時,尤為重要。EJB基礎結構也必須能夠加強Enterprise Beans的訪問控制。如圖1-1所示為EJB的結構。

圖1-1 EJB的結構
EJB的上層分布式應用程序是基于對象組件模型的,低層的事務服務應用了API技術。EJB技術簡化了用Java語言編寫的企業應用系統的開發、配置和執行,其體系結構的規范由Sun Microsystems公司制定。Inprise的EJB容器是基于1.1版的規范。EJB技術定義了一組可重用的組件:Enterprise Beans??梢岳眠@些組件,像搭積木一樣建立分布式應用程序。當把代碼寫好后,這些組件就被組合到特定的文件中去,每個文件有一個或多個Enterprise Beans,再加上一些配置參數。最后,這些Enterprise Beans被配置到一個裝有EJB容器的平臺上??蛻裟軌蛲ㄟ^這些Beans的home接口,定位到某個Beans,并產生該Beans的一個實例。這樣,客戶就能夠調用Beans的應用方法和遠程接口。
建立一個基于對象的、多層的、分布式的系統有三種途徑:無狀態服務途徑、基于會話途徑和持續對象途徑。
無狀態的服務是通過對象的操作提供一種功能的函數,但是不保持會話的狀態。當一個客戶使用無狀態的對象時,客戶不能夠提供上一次操作的信息。
基于會話的設計產生了一個中間層的對象,稱為一個會話(Session),這個會話可以看成是客戶的代理。典型的會話的生命是由客戶和所在的服務程序決定的。客戶如果完成了會話就可以將對象移走,如果服務終止了,會話對象就會超時,會話對象就會變得無效。
持續對象設計模式綁定了存在于數據庫中的一塊數據,提供了操作這塊數據的一些操作。持續對象是由多個客戶共享的,其生命期是由存儲數據的數據庫所決定的。
EJB規范中將這些分別稱作:stateless Session,stateful Session和Entiry Beans。Session Beans模式就是基于會話的設計模式,Entiry Beans模式就是持續對象設計模式,每種模式都定義了一些接口和命名約定。
1.2.2 EJB的體系結構
EJB服務器作為容器和低層平臺的橋梁,管理著EJB容器和函數,它向EJB容器提供了訪問系統服務的能力。例如:數據庫的管理和事務的管理。所有的EJB實例都運行在EJB容器中。容器提供了系統級的服務,控制了EJB的生命周期。EJB分布式應用程序是基于對象組件模型的,低層的事務服務使用了API技術。EJB技術簡化了用JAVA語言編寫的企業應用系統的開發、配置??蛻裟軌蛲ㄟ^這些Beans的home接口,定位到某個Beans,并產生該Beans的一個實例。這樣,客戶就能夠調用Beans的應用方法和遠程接口。EJB中有一些易于使用的管理工具,如:Security——配置描述器(The Deployment Descriptor)定義了客戶能夠訪問的不同的應用函數。容器通過只允許授權的客戶訪問這些函數以達到這個效果。Remote Connectivity——容器為遠程鏈接管理著低層的通信issues,而且對Enterprise Beas的開發者和客戶都隱藏了通信細節。EJB的開發者在編寫應用方法的時候,就像是在調用本地的平臺一樣??蛻粢膊磺宄麄冋{用的方法可能是在遠程被處理的。Life Cycle managment——客戶簡單地創建一個Enterprise Beans的實例,并通常取消一個實例。而容器管理著Enterprise Beans的實例,使Enterprise Beans實現最大的效能和內存利用率。容器能夠激活和使Enterprise Beans失效,保持眾多客戶共享的實例池。Transaction management——配置描述器定義了Enterprise Beans的事務處理的需求,容器管理著那些管理分布式事務處理的復雜的issues。這些事務可能要在不同的平臺之間更新數據庫,容器使這些事務之間互相獨立,互不干擾,保證所有的更新數據庫都是成功發生的,否則,就回滾到事務處理之前的狀態。
EJB組件是基于分布式事務處理的企業級應用程序的組件。所有的EJB都有如下特點:
(1)包含了處理企業數據的應用邏輯。
(2)定義了EJB的客戶界面。該界面不受容器和服務器的影響。于是,當一個EJB被集合到一個應用程序中去時,不用更改代碼和重新編譯。
(3)Enterprise Beans能夠被定制。
(4)各種系統級的服務,例如安全和事務處理的特性,都不是屬于Enterprise Beans Class的,而是由配置和組裝應用程序的工具來實現。
有兩種類型的EJB:Session Beans和Entity Beans。Session Beans是一種作為單用戶執行的對象。作為對遠程任務請求的響應,容器產生一個Session Beans的實例。一個Session Beans有一個用戶,某種程度上,一個Session Bean對于服務器來說就代表了它的那個用戶。Session Beans也可以用于事務,能夠更新共享的數據,但不直接描繪這些共享數據。Session Beans的生命周期相對來說是比較短的。典型地,只有當用戶保持會話時,Session Beans才是活著的,一旦用戶退出Session Beans就不再與用戶相聯系。Session Beans被看成是瞬時的,因為如果容器崩潰了,那么,用戶必須重新建立一個新的Session對象來繼續會話。
Session Bean聲明了與用戶的互操作或者會話,也就是說,在客戶會話期間,Session Bean通過方法的調用,掌握用戶的信息。一個具有狀態的Session Bean稱為有狀態的Session Bean。當用戶終止與Session Beans互操作時,會話終止了,而且,Bean也不再擁有狀態值。Session Bean也可能是一個無狀態的session Bean,無狀態的Session Beans并不掌握其客戶的信息或狀態。用戶能夠通過調用Beans的方法來完成一些操作。但是,Beans只是在方法調用時才知道用戶的參數變量,當方法調用完成后,Beans并不繼續保持這些參數變量。所有無狀態的Session Beans的實例都是相同的,除非正在方法調用期間。這樣,無狀態的Session Beans就能夠支持多個用戶。容器能夠聲明一個無狀態的Session Beans,能夠將任何Session Beans指定給任何用戶。
Entity Beans為數據庫中的數據提供了一種對象視圖,例如:一個Entity Beans能夠模擬數據庫表中一行相關的數據。多個client能夠共享訪問同一個Entity Beans。多個client也能夠同時訪問同一個Entity Beans。Entity Beans通過事務的上下文來訪問或更新下層的數據,保證了數據的完整性。Entity Beans能存活相對較長的時間,并且狀態是持續的,只要數據庫中的數據存在,Entity Beans就一直存活或者服務進程來。即使EJB容器崩潰了,Entity Beans也是存活的。Entity Beans生命周期能夠被容器或者Beans自己管理。如果由Beans自己管理,就必須寫Entity Beans的代碼,包括訪問數據庫的調用。
1.3 JavaBean與EJB的不同
JavaBean和EJB有一些相同之處,都是用一組特性創建的,以執行其特定任務的對象或組件。它們還具有從當前所駐留服務器上的容器獲得其他特性的能力,這使得Bean的行為可以根據特定任務和所在環境的不同而有所不同,進而開辟了巨大商機。由于JavaBean是與平臺無關的,所以對于將來的解決方案,供應商可以很容易地向不同用戶推出其客戶機方的JavaBean,而不必創建或維護不同的版本。這些JavaBean可以與執行商業功能(例如訂購、信用卡處理、電子匯款、存貨分配、運輸等)的EJB配合使用,這正是組件代理(WebSphere Application Server企業版)設計提供的巨大潛力。
JavaBean是一種組件,它在內部有接口或有與其相關的屬性,以便不同人在不同時間開發的Bean可以詢問和集成。可以先構建一個Bean,然后在以后構造時將它與其他Bean綁定。這種過程提供了先構建,然后重復使用的方法,這就是組件的概念。可以將這種單一應用程序部署成獨立程序、ActiveX組件或嵌入在瀏覽器中。JavaBean因有外部接口(即屬性接口)而與純對象不同。這種接口允許工具讀取組件要執行的功能,將其與其他Bean掛鉤,以及將其插入其他環境。JavaBean設計成對單一進程而言是本地的,在運行時通常是可視的,這種可視組件可能是按鈕、列表框、圖形或圖表——但這不是必需的。
Server Bean或EJB是部署在服務器上的可執行組件或商業對象。有一個協議允許對其進行遠程訪問或在特定服務器上安裝或部署它們,有一系列機制允許它們將服務安全性、事務行為、并發性(由多個客戶機同時訪問的能力)和持久性(其狀態可以保存多久)的主要方面授權給EJB服務器上其所在的容器。當安裝在容器中時,它們獲得各自的行為,該行為提供不同質量的服務,因此,選擇正確的EJB服務器至關重要,這正是IBM WebSphere企業版的優勢所在。
EJB是運行在服務器上、并由客戶機調用的非可視遠程對象,可通過多個非可視JavaBean構建EJB。它有一個部署描述符,其目的與JavaBean屬性相同:它是以后可由工具讀取的Bean的描述。EJB還獨立于平臺,一旦編寫好,可以在任何支持Java的平臺(包括客戶機和服務器)上使用。因為EJB由諸如IBM VisualAge for Java這樣的工具集生成,所以,它是基于服務器的對象,并用于遠程調用。它們可以安裝在EJB服務器上,并像調用其他CORBA遠程對象那樣獲得進行調用的遠程接口。
ActiveX對象:可以將JavaBean部署成ActiveX對象,雖然EJB的代理也可以這樣做,但是,由于ActiveX運行在桌面上,所以,EJB本身不能成為ActiveX對象。若要在與平臺相關的、僅Windows平臺上做到這一點,開發人員可以將JavaBean換成ActiveX組件。EJB的主要好處在于:構建Bean時,Bean開發人員可以規定需要什么類型的行為,而不必規定如何去做。開發分為兩部分:第一步,程序員開發Bean,然后驗證。它可與構建工具一起工作,并包括標識所需服務質量行為種類的部署描述符。第二步,另一個程序員可以采用這個Bean,并使用讀取EJB部署描述符的部署工具,然后,將該Bean安裝到Enterprise Java Server上的容器中。在第二步中,部署工具采取一些操作——這可能意味著生成如狀態保存代碼、放入事務掛鉤,或執行安全性檢查這樣的代碼。所有這些操作由部署工具生成,Bean開發人員和部署人員可以是不同的人。
可以通過使用部署工具,將任何獨立于平臺的JavaBean改寫成具有可靠服務質量、特定于平臺的EJB,以滿足現有商業系統和應用程序的特定需求,這就是EJB服務器對集成系統、網絡和體系結構如此重要的原因所在。Bean的全部意義不只是其現有能力,更在于其可以為商業提供有競爭力的潛在能力。IT設計師和應用開發人員可以將精力完全集中在商業邏輯,而將如事務、持久性和安全性的底層工作留給服務器。
1.4 備受爭議的EJB
EJB是一種企業應用技術,旨在建立一個企業應用開發框架,但從其誕生之日起,質疑之聲就一直不斷,復雜、難以使用、性能低下、煩瑣等。在Java發展史上,曾有過很多重要的時刻。如在20世紀末,也就是在1998年,JSP和EJB的誕生就是一個不同尋常的時刻。JSP誕生后,立刻引起了很多開發人員的注意,并很快成為Web開發的主流。而幾乎和它同時誕生的EJB 1.0卻一直備受冷落。在EJB 1.0誕生后的幾年,Sun又推出了EJB 2.0規范,不過它的命運也與EJB 1.0相同,還是沒有翻身。這其中最大的原因,我想是因為Sun沒有兌現它的承諾而造成的。
Sun在發布J2EE相關規范和產品時承諾,J2EE將會使開發變得更容易,從而會顯著降低開發成本。但在J2EE發布時,滿心歡喜的人們卻發現,被認為是J2EE中最有價值的組成部分——EJB卻是如此復雜。在編寫EJB時需要進行大量的配置,而且還需要實現一大堆的接口。這不但沒有降低開發難度,反而成為很多開發人員的噩夢。在EJB 2.x剛出來的幾年,國內有很多程序員盲目跟風,但當時,他們中的大多數都只是停留在EJB的“名詞”階段。而當他們開始熟悉并使用EJB時,卻發現并不是像他們想得那樣美妙。
實體Bean在EJB 2.0后就成為EJB最重要的一部分,但是它的概念從來就沒清楚過。如Sun建議將業務邏輯代碼放到會話Bean中,也就是說,前端應該直接訪問會話Bean。而作為對數據直接封裝的實體Bean卻提供了遠程接口,這也就意味著前端也可以直接訪問實體Bean,這就與多程序應用結構不太符合。再如,實體Bean既然是對數據的原始封裝,那為什么要提供事務、安全這些業務邏輯層的功能呢?更不可思議的是,實體Bean既然提供了本地接口,那又為什么不通過本地接口,而要通過JNDI查找呢?這些概念上的混淆使得EJB更加難以使用。
EJB技術正在像其他輝煌過的技術一樣走到一個關口。2000年以前,這項技術充滿了傳奇色彩,被大批企業不假思索地接受。然而,理想畢竟是理想,經過了幾年的發展,今天這項技術卻正在被懷疑或者說至少讓技術人員猶豫不決?,F實是:J2EE的對手出來了,.NET似乎又有著后發的技術優勢。大部分探討和爭論已經開始轉向這兩個體系結構的對比。Java陣營內部同樣發出了懷疑的聲音,最直接的就是對EJB的攻擊,因為人們發現這項技術所做的承諾似乎都走向了相反的方向。EJB不成熟,但不等于可以輕易被否定——是EJB使得很多普通的程序員能夠介入原來貴族似的組件開發,甚至是在Windows上面開發UNIX上的組件,EJB的歷史問題大多數在于將這種技術錯誤地濫用:一個瀏覽人數少得可憐的廣告瀏覽程序也要用組件,為一個只想簡單算出庫存的客戶設計了所謂N年后才需要的擴展性。同樣,現實中在這一技術擅長的領域,至少目前還無法找到更強大的競爭者。
J2EE是第一個為業界所廣為接受的完整的企業應用框架,而EJB在其中扮演著重要角色。在J2EE框架的支持下,運行在EJB容器中的EJB,完全符合企業應用關于分布、移植、安全和交易的要求。這對于企業應用的開發者來說,意義非同尋常。首先,大家可以在一個公共的平臺技術上構建自己的企業應用,不必絞盡腦汁“發明”自己的“輪子”,從而節省大量無謂的、重復性的技術和時間投入;其次,一個公開的平臺,讓大量的企業應用開發者有了共同語言,可以相互交流平臺的使用經驗和教訓。這樣,隨著平臺之上企業應用的不斷增加,平臺的優劣得失一覽無余,有利于平臺的改進和發展。
1.5 EJB 3.0規范全新體驗
最近,期待已久的EJB 3.0規范發布了初稿,兩個重要的變更分別是:使用了Java 5中的程序注釋工具和基于Hibernate的O/R映射模型。
1.5.1 EJB 3.0中兩個重要的變更
EJB 3.0中兩個重要的變更分別是:使用了Java5中的程序注釋工具和基于Hibernate的O/R映射模型。
1.Java 5中的程序注釋工具
Java 5(以前叫J2SE 1.5或Tiger)中加入了一種新的程序注釋工具。通過該工具用戶可以自定義注釋標記,通過這些自定義標記來注釋字段、方法、類等。這些注釋并不會影響程序的語義,但是可以通過工具(編譯時或運行時)來解釋這些標記,并產生附加的內容(比如部署描述文件),或者強制某些必須的運行時行為(比如EJB組件的狀態特性)。注釋的解析可以使用源文件的解析(比如編譯器或IDE工具)或者使用Java 5中的APIs反射機制,注釋只能被定義在源代碼層。由于所有被提交到EJB 3.0草案中的注釋標記都有一個運行時的RetentionPolicy,因此,會增加類文件占用的存儲空間,但這卻給容器制造商和工具制造商帶來了方便。在已經提交的EJB 3.0規范中主要涉及兩個方面的改變:
(1)一套以注釋為基礎的EJB編程模型,再加上EJB 2.1中定義的通過部署描述符和幾個接口定義的應用程序行為。
(2)新的實體Bean持久化模型,EJBQL也有許多重要的改變。
還有一些有關上述的提議,比如:一個新的客戶端編程模型。業務接口的使用,以及實體Bean的生命周期。請注意,EJB 2.1編程模型(包括部署描述符和home/remote接口)仍然是有效的。新的簡化模型并沒有完全取代EJB 2.1模型。
EJB規范組織一個重要的目標是減輕原始代碼的數量,為此他們給出了一個完美而簡潔的辦法。在EJB 3.0里,任何類型的企業級Bean只是一個加了適當注釋的簡單Java對象(POJO)。注釋可以用于定義Bean的業務接口、O/R映射信息和資源引用信息,效果與在EJB 2.1中定義部署描述符和接口是一樣的。在EJB 3.0中,部署描述符不再是必須的了;home接口也沒有了,也不必實現業務接口(容器可以完成這些事情)。比如,可以使用@Stateless注釋標記類把Java類聲明為一個無狀態會話Bean。對于有狀態會話Bean來說,@Remove注釋可以用來標記一個特定的方法,通過這個注釋來說明在調用這個方法之后,Bean的實例將被清除掉。為了減少描述組件的說明信息,規范組織還采納了由異常進行配置(configuration-by-exception)的手段,意思是可以為所有的注釋提供一個明確的默認值,這樣,多數常規信息就可以據此推斷得出。
2.新的持久化模型
新的實體Bean也是一個加了注釋的簡單Java對象(POJO)。一旦被EntityManager訪問,它就成為了一個持久化對象,并且成為持久化上下文(context)的一部分。一個持久化上下文與一個事務上下文是松耦合的,嚴格地講,它隱式地與一個事務會話共存。
實體關系與O/R映射也是通過注釋來定義的,并提供幾種不同的數據庫規范操作,在EJB 2.1中,這些是需要通過開發人員自己的設計模式或者其他技術來完成的(比如,自增長主鍵策略)。
EJB 3.0必須實現的重要目標之一是,要使之成為更加有用和更易于使用的開發工具。Sun公司的Linda DeMichiel認識到,要成功實現這一目標,EJB 3.0必須基于開發人員今天正在使用的現有庫;否則,它將會導致一種困難的升級操作,并且,可能不會引起足夠的重視。因此,來自Oracle,JBoss,Apache,BEA,Novell, Google的成員和其他方面的專家都被邀請參與制訂這一規范。這個小組的目標是,生產一種規范,能夠使得EJB更易于開發,并且,還要創建一種便于開發人員能夠容易地實現升級的持久性存儲標準。當這個小組開始開發EJB 3.0規范時,他們很快認識到,其中很多特征應該在功能上與所有的主要供應商和庫保持一致。
(1)EntityManager
EntityManager負責處理一個事務,在JDO中,它被稱作持久性存儲管理器,而在Hibernate中稱它為一個會話。在GlassFish工程中,EntityManager被這樣描述:
其實,一個EntityManager實例與一個持久性存儲上下文相關聯。一個持久性存儲上下文是一組實體實例,其中的任何一個持久性實體都是唯一的一個實體實例。在該持久性存儲上下文中,實體實例及其生命周期都是可被管理的。EntityManager定義了用于與持久性存儲上下文進行交互的方法。EntityManager API用于創建和刪除持久性實體實例,通過其主鍵查找實體和查詢實體。
這個可由一個給定的EntityManager實例管理的實體集合是通過一個持久性存儲單元進行定義的。一個持久性存儲單元定義了所有類的集合,這些類是相聯系的或由應用程序加以分組,并且,它們必須共存于其到單個數據庫的映射中。
(2)命名查詢
一個命名查詢是一個預定義的查詢,它被賦予一個名字,這樣,就可以在以后通過該名字加以存取。用數據庫術語來說,命名查詢被稱作存儲過程。當結合本機查詢時(見下一節),數據庫查詢應該是非常輕松的。
(3)本機查詢
本機查詢允許直接從EJB中全面使用SQL語言,而不是使用具有很多限制性的實體查詢語言。現在,我們有可能直接在數據庫上調用count()、max()和其他功能而不必費其他周折。
(4)回調監聽器
回調監聽器是一種事件監聽器,或用數據庫術語來說,是一種觸發器。它們支持當一個事件發生時進行代碼調用。
(5)脫離/重新依附對象
能夠脫離開一個EntityManager的控制范圍而又能夠重新返回而被持續化存儲,這在EJB 3.0版本之前是無法實現的。以前,為了實現這一目的,必須把來自于一個對象的值復制到一個POJO(普通Java對象)中,然后再被往回復制。在EJB 3.0之前,總是使用值、對象,并且把來自于EJB的值復制到一個POJO中;然后,在前端使用該對象。如果該POJO中的一個值被改變,它將不得不被“推回”到該EJB;然后,該值被復制回來。如今,這種“混亂”狀態已經不復存在。一個對象甚至能夠完全離開JVM,并且在以后某個時期返回,被重新依附,這種改變所帶來的效率是不能被低估的。
值得注意的是,企業Java Bean現在被稱為POJO。隨著注解技術的出現,Java Bean不再需要接口、home和描述符支持文件。僅這個特征就為EJB 3.0贏得了大批開發團隊的青睞。既然企業對象不再被鎖定到應用程序服務器內,那么,我們就不再需要把它們復制進和復制出POJO,這樣就不必把應用程序服務器后端和前端區別得那么嚴格,從而使開發人員能夠更容易地顯示和編輯存儲于EJB中的數據。
1.5.2 Spring與EJB 3.0的比較
Spring框架雖然很流行,但并不是一個標準的開源框架,它主要由interface21 inc開發和控制。Spring框架結構是基于依賴注入(Dependency Injection(DI))的設計模式,可以獨立地在現有的應用服務器上運行,而且大量地使用了XML配置文件。
EJB 3.0是由java community process(jcp)制訂的標準框架,為所有主要的J2EE廠商支持。JBoss已經提供了試用版EJB 3.0標準的開源或商業性質實現。EJB 3.0充分利用了java的注釋。
這兩個框架結構有一個共同的核心設計理念:將中間件服務傳遞給耦合松散的pojos(plain old java objects,簡單潔凈java對象)。因此,開發者可專注于業務邏輯和脫離框架的POJO單元測試。除此之外,由于POJO并不需要繼承框架的類或實現其接口,開發者能夠極其靈活地搭建繼承結構和建造應用。
1.廠商無關性
開發者選擇Java平臺其中最引人注目的理由之一是廠商無關性。EJB 3.0正是一套設計為廠商無關的開放性標準,它被所有企業java社團里開源或商業性質廠商所開發和支持,并將開發者與應用服務器實現完全隔離。例如,JBoss的EJB 3.0實現基于hibernate,Oracle的toplink,但是開發者并不需要學習hibernate或toplink的具體API來使應用可在JBoss或Oracle上運行。廠商無關性使EJB 3.0與現今其他POJO中間件框架區別開來。
另一方面,Spring一直以來都是非標準的技術,在未來可預知的一段時間內,這種情況將持續下去。雖然可以在任何應用服務器上使用Spring框架,但Spring應用會被鎖入在Spring本身或選擇整合進Spring的具體服務中。
Spring框架是一個開源項目,但同時它有一個XML格式的配置文件和編程接口。當然,任何一個非標準的產品都會有這種鎖入(lock-in)的情況,并不是Spring特有的,但Spring應用的長期生存能力仍然還得依賴于該配置文件和編程接口(或者是interface21公司,它雇傭了大部分Spring核心開發人員)。除此之外,假如用到任何一個具體的Spring服務,例如,Spring事務管理器或Spring mvc,那么就會被鎖入到這些API里。
Spring的應用對終端用戶是不可知的,例如,對數據持久服務。Spring框架兼容不同的DAO和JDBC的模板幫助類,如Hibernate,ibatis和jdo。所以,假如需要為Spring應用切換在數據持久化服務(例如從JBDC到Hibernate),則需要修改代碼以適合新的模板幫助類。
2.服務整合
從一個很高的角度上看,Spring框架處于應用服務器和服務庫的上方。服務整合的代碼(如數據訪問模板和幫助類)屬于框架,并暴露于應用開發者。相反,EJB 3.0框架與應用服務器則高度整合,并且服務整合代碼也包裝在一個標準接口后面。
因此,實現EJB 3.0的廠商可以大大優化整體性能和提升開發者的體驗。例如,在JBoss EJB 3.0的實現中,當在用Entity Manager持久化一個Entity Bean時,后臺的Hibernate會話事務已經自動地綁定到調用方法的jta的事務上,在jta事務提交的同時,Hibernate會話事務也提交了。甚至可以使用一個簡單的@persistencecontext注釋(稍候例子演示),將EntityManager及其后臺的Hibernate事務綁定到一個Stateful Session Bean的應用事務中。在一個會話中應用事務橫跨多個線程,這在事務性網頁應用很有用,例如,多頁面的購物車。
由于高度整合的EJB 3.0的框架使簡單、集成的編程接口成為可能,Oracle EJB 3.0框架及其后臺的toplink持久化服務也可以同樣程度地整合。
另一個EJB 3.0整合服務的例子是集群支持。假如在一個服務器集群上部署了一個EJB 3.0的應用,所有容錯(fail-over)、負載均衡、分布式緩沖和狀態復制都已經自動為應用所獲得。而后臺的集群支持則被隱藏在EJB 3.0的框架后,對EJB 3.0開發者來說,這些都是完全透明不可見的。
在Spring里,很難優化框架和服務之間的通信。例如,為了使用Spring里的聲明事務服務來管理hibernate事務,必須顯式地在XML文件中配置Spring Transaction Manager和Hibernate Session Factory對象。Spring必須顯式地管理橫跨多個http請求的事務。除此之外,沒有其他方法能夠均衡Spring應用里的集群。
3.服務組合的彈性
由于Spring的服務整合代碼作為編程接口的一部分暴露在外,應用開發者有按自己需求裝配服務的彈性,這個特點使用戶能夠組合自己的輕量級應用服務器。Spring的一個普遍用法就是將Tomcat和Hibernate組合在一起支持數據庫驅動的web應用,而EJB 3.0應用服務器不提供這種根據需求任意挑揀服務的彈性空間。大多數時間得到的只是一系列包裝好的特性,其中一些可能根本就不需要。但是,如果應用服務器像JBoss一樣提供一個模塊性的內部設計,那么就可以只取其中一部分,而把不必要的部分剝去。在任何情況,去自定義一個功能強大的應用服務器那是沒有什么價值的。當然,假如應用已經超過單個點,那么你應該加入常用服務器上的服務,例如,資源池(resource pooling)、消息隊列(message queuing)和集群(clustering)。就總體資源消耗而言,Spring解決方法和其他EJB 3.0解決方法一樣是重量級的。
在Spring框架里,具有彈性的服務裝配使得將虛擬對象而不是真正的業務對象綁定到應用中做脫離容器的單元測試更簡單。在EJB 3.0應用中,大多數組件都是簡單POJO,可以很容易地在容器外被測試。但是,對于與容器服務相關的對象(例如持久化實體管理器Entity Manager),建議用容器內測試,因為這樣比虛擬對象測試方法更簡單、強壯及準確。
4.xml vs.注解
從應用開發者的觀點來看,Spring的編程開發接口主要基于xml配置文件,而EJB 3.0則廣泛地應用Java注解。xml可以表達復雜的關系,但是它太冗長且不夠健壯;注解簡單明了,但是很難在其中表達復雜或繼承性的關系。
Spring選擇xml或EJB 3.0選擇注解,都是由他們兩者框架后的體系結構決定的。因為注解只能容納很少的配置信息,只有整合前的框架(重頭戲都在框架里)才可以把廣泛地使用注解作為配置選擇。正如我們所討論過的,EJB 3.0剛好符合這個要求,而Spring作為一個普通的di框架無法滿足該要求。當然,EJB 3.0和Spring也相互取長補短,在某種程度上他們都支持xml和注解。例如,在EJB 3.0中,xml配置文件作為一個可選的重載機制來改變注解的默認行為,注解也可以配置一些Spring服務。
5.聲明性服務
Spring和EJB 3.0都將運行時服務(例如事務、安全、日志和配置服務)綁定到應用,因為這些服務于應用的業務邏輯是沒有直接聯系的,他們只是由應用本身管理。換句話說,這些服務在運行時由容器透明地應用到應用中。開發者或是管理者通過配置容器,準確地告訴它什么時候、怎樣應用這些服務。
EJB 3.0運用java注解來配置聲明性服務,而Spring使用xml配置文件。在大多數情況下,EJB 3.0注解方式對于這種服務更簡單明了。
6.依賴注入(Dependency Injection, DI)
中間件容器的關鍵好處之一就是它可以讓開發者建造一個關系耦合松散的應用,服務端客戶只需知道服務的接口。容器依據具體的實現實例化服務對象,使他們為客戶端所用。在不改變接口和客戶端代碼的情況下,使得容器可以在多種服務之間很容易地實現切換。
依賴注入的模式是實現耦合松散應用的方法之一。它簡單易用,比其他方法更加明了,比如通過JNDI依賴性查詢或容器回調。使用DI,框架就像一個對象工廠,它創建服務對象,然后按照運行時配置將這些服務對象注入到應用的POJO里。從應用開發者的角度來看,客戶端POJO在被使用時可自動獲得正確的服務對象。
Spring和EJB 3.0都提供廣泛的DI模式支持,但是他們之間仍存在很大的不同之處。Spring支持一般意義上且復雜的DI API,其基于xml配置文件,而EJB 3.0支持大多數普通服務對象(如EJB及context對象)的注入和任何簡單注解的JDNI。
EJB 3.0注解簡單易用。EJB 3.0標準通過注解可以注入服務器資源,但是它也支持用戶定義的應用POJO之間的相互注入。雖然,Spring里基于xml的依賴注入語法復雜,但卻功能強大??梢詫⑷魏蜳OJO注入到另一個POJO,包括用戶在應用定義的POJO。假如想在EJB 3.0應用中用Spring的di功能,則可以通過JNDI把一個Spring Bean factory注入到EJB。在一些EJB 3.0的應用服務器里,廠商可能會額外定義非標準的POJO注入api,一個很好的例子就是JBoss Microcontainer,它比Spring更一般化,因為它處理Aspect-Oriented Programming(AOP)的依賴。
Spring和EJB 3.0雖然都是為了向企業服務提供耦合松散的POJO,都大量地使用了依賴注入,但是卻使用了不同方法。
對于EJB 3.0,基于標準的方案、注解的廣泛使用、與應用服務器的高度整合都使得EJB 3.0擁有更好的廠商無關性、更高的開發效率。依賴注入和集中的xml配置文件協調一致的使用,使開發者能夠構建更有彈性的應用,并且可以同時與幾個應用服務提供者一起協作。
1.5.3 使用EJB 3.0簡化EJB開發
如果用過以前的規范開發EJB,就會發現開發一個類似于HelloWorldEJB這樣簡單的EJB有多困難。至少需要兩個接口、一個Bean類和一個部署描述符。大多數開發人員都在想:我要這些干什么?在Oracle Jdeveloper, Eclipse和XDoclet等IDE中,開發人員可以輕松地完成這些瑣事,但是,在將EJB部署到所選容器之前,開發人員仍需負責編譯這些類并包裝部署描述符。
EJB 3.0使用以下方法來克服這種復雜性:
無需使用接口和部署描述符,而是由容器使用元數據標注生成。
將普通Java類用做EJB,將普通業務接口用于EJB。
簡化容器管理的持久性,EJB 3.0對CMP實體Bean進行了全面的改革,以吸引開發人員的注意力。持久性框架(如OracleAS TopLink)、開放源碼的Hibernate已成為開發J2EE應用程序持久性框架的寵兒,而實體Bean由于既復雜又沉重,已不再受歡迎。EJB 3.0采用了一個類似TopLink和Hibernate的輕量級持久性模型,以簡化容器管理的持久性,而這對開發人員而言無疑很有誘惑力。我們來簡單了解一下該實體Bean計劃關于持久性改進方面的詳細內容,實體Bean正在作為POJO而重獲新生,也將不再需要組件接口。現在實體Bean將被視為純粹的對象,因為它也將支持繼承性和多態性。
簡化EJB的客戶端視圖。
使用EJB(即查找和調用)非常復雜,即使在應用程序中已經對其進行了配置,J2EE 1.4和EJB 3.0規范正是要簡化EJB的客戶端視圖。若現在就想使用EJB,則必須在部署描述符中定義ejb-ref或ejb-local-ref,查找EJB然后再調用。EJB 3.0建議使用另一種方法,即使用setter注入來查找和調用EJB。
1.6 EJB 3.0應用前景
EJB經過了長達8年的臥薪嘗膽,被Sun稱為最簡單的EJB 3.0框架終于在今天正式推出了。也許是Sun意識到了自己的失誤,在制定EJB規范時將以前煩瑣的部分基本都已經去掉了。EJB 3.0看起來就好像新的框架一樣,這一點從它的規范就可以看出,EJB 3.0的規范文件比EJB 2.0規范文件的尺寸小得多。為了使EJB的開發更加容易,EJB規范組織作出的努力是有目共睹的。就像他們說的那樣,一切都會變得簡單,但做到這一點并不容易。目前已經定義了50個注釋標記(還有幾個將在下一個草案中發布),每一個都有自己的默認規則和其他操作。
EJB 3.0和Java EE 5幾乎是同時發布的,因此,EJB 3.0中使用了很多Java EE 5的新特性。如EJB 3.0在定義Bean時(包括會話Bean和實體Bean),不再使用各種各樣的接口,而是使用Java EE 5提供的注釋(annotations)進行定義,無論什么樣的企業級Bean只是一個加了相應注釋的簡單的Java對象(POJO)。不僅如此,EJB 3.0已經全面使用注釋取代了接口,如定義Bean的業務接口、O/R映射信息、資源引用信息等都使用注釋進行描述。由于Hibernate的創始人Gavin King加入了EJB小組,負責制定EJB的O/R映射規范,因此,EJB 3.0的O/R映射十分類似Hibernate,這使得熟悉Hibernate的開發人員學習EJB 3.0非常容易,這也說明EJB 3.0正在和Hibernate走向溶合。同時,Hibernate也提供了兩套API,一套是Hibernate本身的API,另外一套是和EJB 3.0兼容的API。也就是說,只要使用Hibernate第二套API,就可以很容易地將其使用Hibernate的程序移植到EJB 3.0上。雖然EJB 3.0剛剛發布,但已經有很多EJB服務器支持它了,其中跟得最緊的是JBoss,之后WebLogic, WebSphere等也隨之跟進。因此,各大廠商對EJB 3.0還是非??春玫?。
自從那些如Struts, Hibernate, Spring等輕量級的框架開始在市面上出現并流行后,很多開發人員開始跟隨著這些開源大師的指揮棒方向前進,EJB開始逐漸從人們的視線中淡出。但EJB 3.0的問世又將人們的視線拉了回來。畢竟,EJB出自Sun公司,如果它也能像Hibernate,JDO一樣容易使用,那它是非常有前途的(至少我是這么認為的)?,F在EJB 3.0已經和Hibernate在O/R映射上非常相似了,在未來,EJB 3.0也許將成為輕量級框架的一員,讓我們拭目以待吧!
1.7 小結
本章首先介紹了EJB的基本概念、基礎結構和體系結構,使讀者對EJB有了基本的了解,討論了EJB和JavaBean的區別,以及EJB的優缺點。然后介紹了EJB 3.0的新規范,比較了EJB 3.0和以前版本的重要改進,比較了EJB 3.0和Spring的優缺點,及EJB 3.0如何簡化EJB的開發過程。最后展望了EJB 3.0的應用前景,使讀者對EJB有了更深刻的認識。
- Core Data應用開發實踐指南
- 業務驅動的推薦系統:方法與實踐
- Android游戲開發大全
- SQL Server應用與開發范例寶典
- Swift從入門到精通(正式版)
- 卡爾曼濾波原理及應用:MATLAB仿真(第2版)
- Visual Basic編程寶典(十年典藏版)
- 現代API:通往架構師之門
- 軟件開發大講堂·從入門到精通-第一輯(套裝共5冊)
- 構建跨平臺APP:jQuery Mobile移動應用實戰(第2版) (跨平臺移動開發叢書)
- 軟件單元測試
- 移山之道:VSTS軟件開發指南
- Intel Quartus Prime數字系統設計權威指南:從數字邏輯、Verilog HDL 到復雜數字系統的實現
- 現代軟件測試技術之美
- 案例解說MATLAB典型控制應用