love fish大鵬一曰同風(fēng)起,扶搖直上九萬里

          常用鏈接

          統(tǒng)計

          積分與排名

          friends

          link

          最新評論

          使用EJB3.O簡化EJB開發(fā)(全中文)(轉(zhuǎn))

          使用EJB3.O簡化EJB開發(fā)??? 原著:Debu Panda

          我們引入EJB來構(gòu)造分布式的組件。它誕生之時是為了解決所有CORBA的問題和復(fù)雜性。經(jīng)歷過幾次重要的版本更新和增加許多特性之后,EJB已經(jīng)成為了J2EE的核心。在早期,很多開發(fā)人員沉迷于EJB甚至在沒有任何意義的情況下在他們的工程中使用EJB。而當他們發(fā)現(xiàn)所使用的工程并沒有質(zhì)的變化后,譴責(zé)EJB成了一種趨勢。

          開發(fā)EJB從來沒有變得簡單甚至在早期的EJB版本規(guī)范中變得更加復(fù)雜。EJB由于其的復(fù)雜性和重量級特性而被比作一只大象。學(xué)多開發(fā)人員感覺EJB象一個油炸圈餅上多余的一層甜糖漿。在現(xiàn)在low carb和Atkins diet大行其道的今天,EJB專家委員會也沒有選擇余地的發(fā)布了體現(xiàn)low carb的EJB規(guī)范來簡化EJB的開發(fā)。EJB3.0專家委員會在2004Javaone大會上發(fā)布了稱之為EJB3.0第一個公開規(guī)范的輕量級模型的范例圖。

          第一眼看到EJB的新模型感覺很不錯。在這篇文章中我們將討論EJB3.0如何使用一個更小而精致的裝配來吸引開發(fā)者的。在接下來的文章中我們將來討論EJB3.0是怎樣簡化持久性模型的。

          整理缺陷

          在我們開始對EJB3.0帶來的新特性進行討論之前,讓我們先分析一下現(xiàn)在EJB模型的復(fù)雜繁瑣。

          • 現(xiàn)在的EJB模型需要建立許多組件接口和實現(xiàn)許多不必要的回滾方法。
          • 組件接口需要實現(xiàn) EJBObject 或者 EJBLocalObject ,并且處理許多不必要的異常。
          • EJB的部署描述復(fù)雜而容易出錯。
          • 基于EJB模型的容器持久化管理的開發(fā)和管理過于復(fù)雜。許多基礎(chǔ)的特征未考慮到,比如使用數(shù)據(jù)庫序列和EJBQL定義一個主鍵的標準方法就非常有限。
          • EJB組件不像是面向?qū)ο蟮模热缭谑褂美^承和多態(tài)時就有太多限制。
          • 一個主要的EJB的缺點是你不能脫離EJB容器測試一個EJB模型且不能在容器內(nèi)調(diào)試一個EJB,這對開發(fā)者無疑是一個可怕的事情。
          如果你使用EJB你需要熟悉調(diào)用和查找EJB的復(fù)雜過程。顯然,你僅僅要在程序中使用EJB但你卻必須知道JNDI詳細的細節(jié)。

          簡化開發(fā)者的觀點

          如果你使用現(xiàn)有版本的EJB你會懂得開發(fā)一個如HelloWorld的簡單的EJB程序是多么困難。你至少需要兩個接口,一個bean類和一個部署描述文件。大多數(shù)的開發(fā)者希望知道為什么我需要所有這些。IDEs(開發(fā)環(huán)境工具)象OracleJDeveloper, EclipseXDoclet簡化了開發(fā)者的做這些普通的工作開發(fā)周期,可是在EJB在你部署到所選擇的容器中之前,編譯類和打包部署文件依然是開發(fā)人員的工作。

          EJB3.0試圖從以下方面簡化復(fù)雜性:

          ·???????? 不必定義接口和部署的描述文件,這些可以由容器使用metadata annotations生成。

          ·???????? 使用常用的Java類作為EJB的類和常用的EJB業(yè)務(wù)接口。

          元數(shù)據(jù)描述(Metadata Annotations)

          EJB3.0非常倚重Metadata Annotations。Metadata Annotations已經(jīng)成為JSR 175標準并且將是J2SE 5.0的一部分。Annotations是一種對象變成的屬性,非常類似與XDoclet。可是不像XDoclet那樣需要預(yù)先編譯,Annotations由Java編譯器在需要編譯的時候編譯。(依賴于@Retention的開始時間)。在開發(fā)人員的觀點,Annotations就如同一個公有的并可以作為類,域,方法,參數(shù),本地變量,構(gòu)造,枚舉和包一樣使用的修改量。你可以在你的Java代碼中附帶特殊的屬性使用Annotations來生成代碼,自動編寫文檔代碼,或者提供如在運行期間增強業(yè)務(wù)層安全或特殊業(yè)務(wù)邏輯的特殊服務(wù)。J2EE1.5(5.0)的目標是簡化開發(fā)人員使用Annotations因此而可能產(chǎn)生一套的Annotations模板。Annotations使用@來標記,如下:

          ? @Author("Debu Panda")

          ? @Bean

          ? public class MySessionBean

          EJB3.0為了簡化開發(fā)因此使用Metadata Annotations來產(chǎn)生許多如接口一樣的人為因素和使用Annotations來替代部署描述文件。

          使用 POJOs 和 POJIs

          在規(guī)范條件中,JavaBeans和接口經(jīng)常分別的涉及到簡單Java對象(POJOs)和簡單Java接口(POJIs)。這些不必要的如Home接口的人為因素已經(jīng)被去掉。

          開發(fā)人員必須在javax.ejb包中實現(xiàn)一個EJB接口(會話bean,實體bean或消息驅(qū)動bean)或者選擇在bean的實現(xiàn)類中使用Annotation。你可以使用無狀態(tài),狀態(tài),消息驅(qū)動或者實體去注釋一個bean類。例如,如果你定義一個無狀態(tài)EJB作為HelloWorld,你可以如下定義EJB:

          @Remote

          ? @Stateless public class HelloWorldBean {

          ?public String sayHello(String s)

          ? { System.out.println("Hello: "+s; }

          ? }

          EJB的接口無論遠程的還是本地的都不必再實現(xiàn)EJBObjectEJBLocalObject。你要么為EJB提供業(yè)務(wù)接口并且實現(xiàn)bean類中的接口,要么需要在部署的時候生成這些接口。雖然會話bean和消息驅(qū)動bean的接口是必須的,但是實體bean的接口是可選的。如果你沒有為你的會話bean實現(xiàn)一個接口,那么它會自動為你生成一個。所生成的接口是本地的還是遠程的取決于你在bean類中的Annotations。如果你仔細看看上面的代碼范例,@Remote很明顯是用來為你的HelloWorld生成一個遠程接口。如果需要,你可以在你的EJB中同時生成遠程和本地接口。

          在上面的例子中,很明顯開發(fā)人員不必再做那些如定義接口和實現(xiàn)回滾方法等這些普通的工作。

          生成接口的名字來源于bean實現(xiàn)類的名字。生成接口對開發(fā)人員來說非常有用。但是我并沒有看到任何如Oracle 的JDeveloper的這些IDE立即實現(xiàn)這種生成接口功能。

          規(guī)范中沒有明確EJB查找時客戶端的需求是什么,也沒有明確我們?nèi)绾伪3诌@些EJB需要調(diào)用的接口。基于以下幾個情況下的原因我將不推薦使用生成接口:

          ·???????? 生成接口的名字來源于bean的名字

          ·???????? 如果你不愿意在EJB中暴露出一些方法而生成接口將默認暴露出所有的方法。

          ·???????? 你需要在客戶端使用接口來調(diào)用EJB.

          去掉回滾方法的需求。

          EJB2.1和更早版本需要實現(xiàn)很多即使對于每個EJB你不需要的一些生命周期的方法,如ejbPassivate, ejbActivate, ejbLoad, ejbStore等等。例如,在無狀態(tài)會話bean中不需要ejbPassivate但是你還是得實現(xiàn)它的方法。現(xiàn)在EJB3.0中類似的常用Java類實現(xiàn)這些生命周期的方法都變成為可選擇的。如果你在EJB中實現(xiàn)任何回滾容器都會調(diào)用這些方法。

          唯一的異常是在你可以使用Removeannotations時一個狀態(tài)會話bean的業(yè)務(wù)方法的ejbRemove方法是狀態(tài)會話bean。如果你使用這個annotations它將在完成annotations方法后(無論正常或非正常)提示容器移除狀態(tài)會話bean實例。例如,你可以指定以下的方式去在checkOut方法執(zhí)行后移除一個狀態(tài)會話bean實例。

          @Stateful public class Cart {

          ...

          ...

          @Remove public void checkOut() {

          ...

          }

          }

          Annotations與部署描述的比較

          在前面我們討論到EJB中不再需要部署描述而由annotations代替。每個部署描述的屬性都將被選擇一個默認值,而開發(fā)人員在直到他們想改變這些屬性的默認值之前不必為這些屬性指定值。這些也能用來為bean的類自身指定使用的annotations。EJB3.0規(guī)范為開發(fā)人員使用bean類型,接口類型,資源引用,事務(wù)屬性,安全等等定義了一組metadata annotations。例如,如果我們可以如下為一個特殊的EJB定義使用資源引用:

          @Resource(name="jdbc/OracleDS", resourceType="javax.sql.DataSource")

          J2EE的提供商如Oracle, BEA, IBM將增加屬性annotations在他們指定的部署描述中,開發(fā)人員將可以使用這些annotations去避免使用部署描述。這看起來對開發(fā)人員十分具有吸引力,特別對XML描述是已經(jīng)感到厭惡的開發(fā)人員,他們早就恨透并想脫離老的那種描述方式,但依然有一些問題使得我們在正式使用annotations時需要謹慎對待。

          • 它違背了我們輕便應(yīng)用程序的目標,因為如果一個EJB如果使用一個提供商指定的部署描述,在重新編譯或打包EJB的時候它必須多次改變。
          • 部署描述對EJB模板提供了全局觀點使得組裝和部署的時候不必考慮單獨的EJB,他們將每個部署需求擰在一起,并且在部署完成之前描述是無效或者不可自動生成的。這對部署員來說是個可怕的事情。
          • 部署描述在EJB模板中被相關(guān)工具用來定義EJBs,當你試圖整合一個和另一個容器的時候非常有用。EJB3.0規(guī)格同樣主張在部署描述中使用重載annotations的方式。可是在規(guī)范里并沒有提到重載annotations的細節(jié)。

          無疑擺脫部署描述將使得新的開發(fā)者開發(fā)更加容易,但是如果使用不當這也將造成管理上的可怕問題。

          簡化持久化容器管理

          CMP實體bean將成為EJB3.0使得開發(fā)人員強制使用的一個主要的檢查方式。持久化框架象如OracleAS TopLink, 開源的Hibernate已經(jīng)成為不像實體bean本質(zhì)上的復(fù)雜和重量級的開發(fā)J2EE持久化框架應(yīng)用的被大家喜愛的方式。 EJB3.0采納了如TopLinkHibernate輕量級的持久化模式來簡化容器持久化管理,這些聽起來更讓開發(fā)人員們欣喜。讓我們簡單的瀏覽一下實體bean的計劃,我們將在另外的文章中討論持久化改進的細節(jié)。

          實體bean作為POJOs已經(jīng)改頭換面,實體bean將不在需要組件接口。實體bean現(xiàn)在看起來是支持繼承和多態(tài)的純粹的對象。

          下面的是關(guān)于實體bean源代碼

          @Entity public class Employee{

          ? private Long empNo;

          ? private String empName;

          ? private Address address;

          ? private Hashmap projects = new Hashmap();

          ? private Double salary;

          ? @Id(generate=SEQUENCE) public Long getEmpNo() {

          ? return empNo;

          ? }

          ? protected void setEmpNo(Long empNo) {

          ? this.empNo = empNo;

          ? }

          ? public String getEmpName() {

          ? return EmpName;

          ? }

          ? public void setEmpName(String EmpName){

          ? this.EmpName = EmpName;

          ? }

          ? @Dependent public Address getAddress() {

          ? return address;

          ? }

          ? public void setAddress(Address address) {

          ? this.address = address;

          ? }

          ? public Set getProjects() {

          ? return projects;

          ? }

          ? public void setProjects(Set projects) {

          ? this.projects = projects;

          ? }

          ? public Double getSalary() {

          ? return salary;

          ? }

          ? public void setSalary(Double salary) {

          ? this.salary = salary;

          ? }

          ? ....

          ? }

          如果你仔細看這些代碼,你可以發(fā)現(xiàn)在現(xiàn)在的實體beanbean類是一個具體的類而不再是一個抽象類。

          EJB QL和實體beanSQL查詢做了多項改進。類似于Hibernate的新的實體管理API和簡化版的TopLink的會話API被建議用來處理實體bean的操作,也就是實體bean的創(chuàng)建,釋放,查找。

          我們將在深入的文章中進一步對建議CMP實體bean的細節(jié)做更多的驗證。

          簡化EJB客戶端

          即使應(yīng)用中EJB是序列化的,使用EJB也就是尋找和調(diào)用也是非常復(fù)雜的。J2EE 1.4 EJB 3.0規(guī)范致力于簡化EJB客戶端。

          如果目前你希望使用EJB你必須在部署描述中定義EJB引用或者EJB本地引用,尋找到EJB然后調(diào)用。如果我們希望調(diào)用HelloWorld EJB,你可以按照下面的簡單方法調(diào)用EJB使用已存在的實現(xiàn)。

          如下在部署描述中找到EJB指示的定義

          <ejb-ref>

          ? <ejb-ref-name>HelloWorldEJB</ejb-ref-name>

          ? <ejb-ref-type>Session</ejb-ref-type>

          ? <home>hello.HelloWorldHome</home>

          ? <remote> hello.HelloWorld</remote>

          ? </ejb-ref>

          然后按照如下方法尋找EJB.你需要明確處理EJB查找和建立一個bean實例時的異常。

          try

          ? {

          ??? Context context = new InitialContext();

          ?????????????? HelloWorldHome helloHome =

          ?????????????? ? (HelloWorld)PortableRemoteObject.narrow(context.lookup

          ???? ("java:comp/env/ejb/HelloWorldEJB"), HelloWorldHome.class);

          ?????????????? HelloWorld hello = helloHome.create();

          ?????????????? ? ....

          ?? }

          ??? catch(RemoteException e)

          ?????????????? {

          ?????????????? ? System.err.println("System/communication error: " + e.getMessage());

          ?????????????? }

          ?????????????? catch(NamingException e)

          ?????????????? {

          ?????????????? ? System.err.println("Communication error: " + e.getMessage());

          ?????????????? }

          ?????????????? catch(CreateException e)

          ?????????????? {

          ?????????????? ? System.err.println("Error creating EJB instance: " + e.getMessage());

          ?????????????? }

          如一個環(huán)境變量的變化一樣,EJB3.0建議使用安放injection的方法查找和調(diào)用EJB.

          下面我們使用安放injection的方法在另一個EJB查找HelloWorldEJB

          @Inject private void setSessionContext(SessionContext ctx)

          ? {

          ? this.ctx = ctx

          ? }

          ? ...

          ? myHello = (HelloWorld)ctx.lookup("java:comp/env/ejb/HelloWorldEJB");

          如果你仔細查看上面的代碼,它依賴的injection使用@Injectset來的指定對SessionContext方法的annotationsinjection 方法將可以在業(yè)務(wù)方法被EJB調(diào)用前被容器調(diào)用來設(shè)定EJBContext

          另一個injected HelloWorld會話bean的直接的范例可以簡化為使用

          @EJB public HelloWorld myHello,這將使得myHelloHelloWorld bean的實例injected

          你可以使用依賴的injection來查詢?nèi)魏晤愋偷沫h(huán)境和資源參考如DataSource, JMS, Mail, Web Service等等。

          容器外部測試可行性

          一個現(xiàn)在EJB開發(fā)者所關(guān)注的不僅僅是EJB開發(fā)的復(fù)雜,也包括了測試的可怕之處。開發(fā)和測試EJB必須需要一個EJB容器并且開發(fā)人員必須熟悉最終部署平臺才可以執(zhí)行測試。這對于許多只在一個主要平臺開發(fā)的企業(yè)開發(fā)人員來說不是主要問題,但是對于支持多個開發(fā)商平臺并且要在維護的多個環(huán)境中測試EJBISV們來說是個大問題。EJB3.0規(guī)范承諾將提供在容器外測試的功能,但是這點在這次的規(guī)范中遺漏掉了。

          結(jié)論

          雖然還有很多關(guān)于打包,裝配和重要的API細節(jié)沒有在這個規(guī)范中提及,但是諸多的建議使得EJB3.0規(guī)范讓企業(yè)級Java開發(fā)人員看起來是恨有前途的。通過這些無疑是從開發(fā)人員到服務(wù)供應(yīng)商都將幫助減少開發(fā)的復(fù)雜性。下面就要看服務(wù)提供商們怎么實現(xiàn),并使得EJB3.0成為企業(yè)級應(yīng)用一個引人矚目的選擇。

          Author Bio 作者自述

          Debu PandaOracle應(yīng)用服務(wù)開發(fā)小組的主要管理者,他的在EJB容器和事務(wù)管理上取得過很多成就。他已經(jīng)有13年的IT產(chǎn)業(yè)的經(jīng)驗并在多家雜志和技術(shù)出版社刊登過很多著作。

          ?

          翻譯問題:

          由于部分英文名詞未敢枉自翻譯,所以留英文原詞在文中

          Cleaning up the Dirty Laundry?????? 整理缺陷

          low carb

          Atkins diet

          metadata annotations???? ?????????????? 元數(shù)據(jù)描述

          Simplifying Client View for EJBs?? 簡化EJB客戶端

          dependency injection???????? ?????????? 依賴型injection

          setter injection????????????? ?????????????? 安放injection

          ISV Independent software vendor 獨立軟件供應(yīng)商

          posted on 2006-06-30 11:49 liaojiyong 閱讀(509) 評論(0)  編輯  收藏 所屬分類: EJB

          主站蜘蛛池模板: 中宁县| 肃宁县| 炉霍县| 内黄县| 黎城县| 凌云县| 卢湾区| 太白县| 克东县| 广宗县| 兰西县| 山东省| 平顺县| 广河县| 仁布县| 龙里县| 池州市| 沿河| 平利县| 修水县| 陈巴尔虎旗| 龙泉市| 扎囊县| 怀宁县| 万荣县| 武胜县| 五大连池市| 丽江市| 深泽县| 佛冈县| 怀柔区| 临江市| 新蔡县| 曲麻莱县| 长岭县| 嘉荫县| 鞍山市| 万荣县| 沙河市| 大荔县| 四川省|