J2EE綜合:Java EJB容器的存取和實現 – JAVA編程語言程序開發技術文章

作為輕量級的容器,Spring常常被認為是EJB的替代品。我們也相信,對於很多(不一定是絕大多數)應用和用例,相對於通過EJB容器來實現相同的功能而言,Sping作為容器,加上它在事務,ORM和JDBC存取這些領域中豐富的功能支持,Spring的確是更好的選擇。

不過,需要特別註意的是,使用瞭Spring並不是說我們就不能用EJB瞭,實際上,Spring大大簡化瞭從中訪問和實現EJB組件或隻實現(EJB組件)其功能的復雜性。另外,如果通過Spring來訪問EJB組件服務,以後就可以在本地EJB組件,遠程EJB組件,或者是POJO(簡單Java對象)這些變體之間透明地切換服務的實現,而不需要修改客戶端的代碼。

本章,我們來看看Spring是如何幫助我們訪問和實現EJB組件的。尤其是在訪問無狀態SessionBean(SLSBs)的時候,Spring特別有用,現在我們就由此開始討論。

訪問EJB1.1.概念要調用本地或遠程無狀態SessionBean上的方法,通常客戶端的代碼必須進行JNDI查找,得到(本地或遠程的)EJBHome對象,然後調用該對象的”create”方法,才能得到實際的(本地或遠程的)EJB對象。前後調用瞭不止一個EJB組件上的方法。

為瞭避免重復的底層調用,很多EJB應用使用瞭服務定位器(ServiceLocator)和業務委托(BussinessDelegate)模式,這樣要比在客戶端代碼中到處進行JNDI查找更好些,不過它們的常見的實現都有明顯的缺陷。例如:

通常,若是依賴於服務定位器或業務代理單件來使用EJB,則很難對代碼進行測試。

在僅使用瞭服務定位器模式而不使用業務委托模式的情況下,應用程序代碼仍然需要調用EJBHome組件的create方法,還是要處理由此引入的異常。導致代碼仍然保留瞭與EJBAPI的耦合性以及EJB編程模型的復雜性。

實現業務委托模式通常會導致大量的冗餘代碼,因為我們不得不編寫很多方法,而它們所做的僅僅是調用EJB組件的同名方法。

Spring采用的方法是允許創建並使用代理對象,一般是在Spring的ApplicationContext或BeanFactory裡面進行配置,這樣就和業務代理類似,隻需要少量的代碼。我們不再需要另外編寫額外的服務定位器或JNDI查找的代碼,或者是手寫的業務委托對象裡面冗餘的方法,除非它們可以帶來實質性的好處。

1.2.訪問本地的無狀態SessionBean(SLSB)

假設有一個web控制器需要使用本地EJB組件。我們遵循前人的實踐經驗,於是使用瞭EJB的業務方法接口(BusinessMethodsInterface)模式,這樣,這個EJB組件的本地接口就擴展瞭非EJB特定的業務方法接口。讓我們假定這個業務方法接口叫MyComponent.

publicinterfaceMyComponent{……

}(使用業務方法接口模式的一個主要原因就是為瞭保證本地接口和bean的實現類之間方法簽名的同步是自動的。另外一個原因是它使得稍後我們改用基於POJO(簡單Java對象)的服務實現更加容易,隻要這樣的改變是有利的。當然,我們也需要實現本地Home接口,並提供一個Bean實現類,使其實現接口SessionBean和業務方法接口MyComponent.現在為瞭把我們Web層的控制器和EJB的實現鏈接起來,我們唯一要寫的Java代碼就是在控制器上公佈一個形參為MyComponent的setter方法。這樣就可以把這個引用保存在控制器的一個實例變量中。

privateMyComponentmyComponent;
publicvoidsetMyComponent(MyComponentmyComponent){
this.myComponent=myComponent;
}

然後我們可以在控制器的任意業務方法裡面使用這個實例變量。假設我們現在從Spring的ApplicationContext或BeanFactory獲得該控制器對象,我們就可以在同一個上下文中配置一個LocalStatelessSessionProxyFactoryBean的實例,它將作為EJB組件的代理對象。這個代理對象的配置和控制器的屬性myComponent的設置是使用一個配置項完成的,如下所示:

<BEANID="MYCOMPONENT"class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean">
<VALUE>myComponent</VALUE>
<VALUE>com.mycom.MyComponent</VALUE>
</BEAN>

</BEAN>

這些看似簡單的代碼背後隱藏瞭很多復雜的處理,比如默默工作的SpringAOP框架,我們甚至不必知道這些概念,一樣可以享用它的結果。BeanmyComponent的定義中創建瞭一個該EJB組件的代理對象,它實現瞭業務方法接口。這個EJB組件的本地Home對象在啟動的時候就被放到瞭緩存中,所以隻需要執行一次JNDI查找即可。每當EJB組件被調用的時候,這個代理對象就調用本地EJB組件的create方法,並調用該EJB組件的相應的業務方法。

在BeanmyController的定義中,控制器類的屬性myController的值被設置為上面代理對象。

這樣的EJB組件訪問方式大大簡化瞭應用程序代碼:Web層(或其他EJB客戶端)的代碼不再依賴於EJB組件的使用。如果我們想把這個EJB的引用替換為一個POJO,或者是模擬用的對象或其他測試組件,我們隻需要簡單地修改BeanmyComponent的定義中僅僅一行Java代碼,此外,我們也不再需要在應用程序中編寫任何JNDI查找或其它EJB相關的代碼。

評測和實際應用中的經驗表明,這種方式的性能負荷極小,(盡管其中使用瞭反射方式以調用目標EJB組件的方法),通常的使用中我們幾乎覺察不出。請記住我們並不想頻繁地調用EJB組件的底層方法,雖然如此,有些性能代價是與應用服務器中EJB的基礎框架相關的。

關於JNDI查找有一點需要註意。在Bean容器中,這個類通常最好用作單件(沒理由使之成為原型)。不過,如果這個Bean容器會預先實例化單件(類似XMLApplicationContext的變體的行為),如果在EJB容器載入目標EJB前載入bean容器,我們就可能會遇到問題。因為JNDI查找會在該類的init方法中被執行並且緩存結果,這樣就導致該EJB不能被綁定到目標位置。解決方案就是不要預先實例化這個工廠對象,而允許它在第一次用到的時候再創建,在XML容器中,這是通過屬性lazy-init來控制的。

盡管大部分Spring的用戶不會對這些感興趣,但那些對EJB進行AOP的具體應用的用戶則會想看看LocalSlsbInvokerInterceptor.

作為輕量級的容器,Spring常常被認為是EJB的替代品。我們也相信,對於很多(不一定是絕大多數)應用和用例,相對於通過EJB容器來實現相同的功能而言,Sping作為容器,加上它在事務,ORM和JDBC存取這些領域中豐富的功能支持,Spring的確是更好的選擇。

不過,需要特別註意的是,使用瞭Spring並不是說我們就不能用EJB瞭,實際上,Spring大大簡化瞭從中訪問和實現EJB組件或隻實現(EJB組件)其功能的復雜性。另外,如果通過Spring來訪問EJB組件服務,以後就可以在本地EJB組件,遠程EJB組件,或者是POJO(簡單Java對象)這些變體之間透明地切換服務的實現,而不需要修改客戶端的代碼。

本章,我們來看看Spring是如何幫助我們訪問和實現EJB組件的。尤其是在訪問無狀態SessionBean(SLSBs)的時候,Spring特別有用,現在我們就由此開始討論。

訪問EJB1.1.概念要調用本地或遠程無狀態SessionBean上的方法,通常客戶端的代碼必須進行JNDI查找,得到(本地或遠程的)EJBHome對象,然後調用該對象的”create”方法,才能得到實際的(本地或遠程的)EJB對象。前後調用瞭不止一個EJB組件上的方法。

為瞭避免重復的底層調用,很多EJB應用使用瞭服務定位器(ServiceLocator)和業務委托(BussinessDelegate)模式,這樣要比在客戶端代碼中到處進行JNDI查找更好些,不過它們的常見的實現都有明顯的缺陷。例如:

通常,若是依賴於服務定位器或業務代理單件來使用EJB,則很難對代碼進行測試。

在僅使用瞭服務定位器模式而不使用業務委托模式的情況下,應用程序代碼仍然需要調用EJBHome組件的create方法,還是要處理由此引入的異常。導致代碼仍然保留瞭與EJBAPI的耦合性以及EJB編程模型的復雜性。

實現業務委托模式通常會導致大量的冗餘代碼,因為我們不得不編寫很多方法,而它們所做的僅僅是調用EJB組件的同名方法。

Spring采用的方法是允許創建並使用代理對象,一般是在Spring的ApplicationContext或BeanFactory裡面進行配置,這樣就和業務代理類似,隻需要少量的代碼。我們不再需要另外編寫額外的服務定位器或JNDI查找的代碼,或者是手寫的業務委托對象裡面冗餘的方法,除非它們可以帶來實質性的好處。

1.2.訪問本地的無狀態SessionBean(SLSB)

假設有一個web控制器需要使用本地EJB組件。我們遵循前人的實踐經驗,於是使用瞭EJB的業務方法接口(BusinessMethodsInterface)模式,這樣,這個EJB組件的本地接口就擴展瞭非EJB特定的業務方法接口。讓我們假定這個業務方法接口叫MyComponent.

<p style="T

You May Also Like