溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

J2EE中使用Spring AOP框架和EJB組件(1)

發(fā)布時間:2020-08-14 16:00:48 來源:ITPUB博客 閱讀:193 作者:lonlux2 欄目:編程語言

J2EE中使用Spring AOP框架和EJB組件(1)

[@more@]本文介紹了一種把J2EE應(yīng)用程序中的EJB轉(zhuǎn)換為Spring托管組件的方法,以及轉(zhuǎn)換之后可以采用的強大技術(shù)。它還給出了幾個實際的例子,說明如何借助于Spring的AOP框架、應(yīng)用面向方面的方法來擴展J2EE應(yīng)用程序,并在不修改現(xiàn)有代碼的情況下實現(xiàn)新的業(yè)務(wù)需求。

快速發(fā)展的開發(fā)人員社區(qū)、對各種后端技術(shù)(包括JMS、JTA、JDO、Hibernate、iBATIS等等)的支持,以及(更為重要的)非侵入性的輕量級IoC容器和內(nèi)置的AOP運行時,這些因素使得Spring Framework對于J2EE應(yīng)用程序開發(fā)十分具有吸引力。Spring托管的組件(POJO)可以與EJB共存,并允許使用AOP方法來處理企業(yè)應(yīng)用程序中的橫切方面——從監(jiān)控和審計、緩存及應(yīng)用程序級的安全性開始,直到處理特定于應(yīng)用程序的業(yè)務(wù)需求。

本文將向您介紹Spring的AOP框架在J2EE應(yīng)用程序中的實際應(yīng)用。

簡介

J2EE技術(shù)為實現(xiàn)服務(wù)器端和中間件應(yīng)用程序提供了堅實的基礎(chǔ)。J2EE容器(比如BEA WebLogic Server)可以管理系統(tǒng)級的元素,包括應(yīng)用程序生命周期、安全性、事務(wù)、遠程控制和并發(fā)性,而且它可以保證為JDBC、JMS和JTA之類的常見服務(wù)提供支持。然而,J2EE的龐大和復雜性使開發(fā)和測試變得異常困難。傳統(tǒng)的J2EE應(yīng)用程序通常嚴重依賴于通過容器的JNDI才可用的服務(wù)。這意味著需要大量直接的JNDI查找,或者要使用Service Locator模式,后者稍微有所改進。這種架構(gòu)提高了組件之間的耦合度,并使得單獨測試某個組件成為幾乎不可能實現(xiàn)的事情。您可以閱讀Spring Framework創(chuàng)建者所撰寫的J2EE Development without EJB一書,其中深入分析了這種架構(gòu)的缺陷。

借助于Spring Framework,可以將使用無格式Java對象實現(xiàn)的業(yè)務(wù)邏輯與傳統(tǒng)的J2EE基礎(chǔ)架構(gòu)連接起來,同時極大地減少了訪問J2EE組件和服務(wù)所需的代碼量?;谶@一點,可以把傳統(tǒng)的OO設(shè)計與正交的AOP組件化結(jié)合在一起。本文稍后將會演示如何重構(gòu)J2EE組件以利用Spring托管的Java對象,然后應(yīng)用一種AOP方法來實現(xiàn)新特性,從而維護良好的組件獨立性和可測試性。

與其他AOP工具相比,Spring提供了AOP功能中的一個有限子集。它的目標是緊密地集成AOP實現(xiàn)與Spring IoC容器,從而幫助解決常見的應(yīng)用問題。該集成是以非侵入性的方式完成的,它允許在同一個應(yīng)用程序中混合使用Spring AOP和表現(xiàn)力更強的框架,包括AspectJ。Spring AOP使用無格式Java類,不要求特殊的編譯過程、控制類裝載器層次結(jié)構(gòu)或更改部署配置,而是使用Proxy模式向應(yīng)該由Spring IoC容器托管的目標對象應(yīng)用通知。

可以根據(jù)具體情況在兩種類型的代理之間進行選擇:

◆第一類代理基于Java動態(tài)代理,只適用于接口。它是一種標準的Java特性,可提供卓越的性能。

◆第二類代理可用于目標對象沒有實現(xiàn)任何接口的場景,而且這類接口不能被引入(例如,對于遺留代碼的情況)。它基于使用CGLIB庫的運行時字節(jié)碼生成。

對于所代理的對象,Spring允許使用靜態(tài)的(方法匹配基于確切名稱或正則表達式,或者是注釋驅(qū)動的)或動態(tài)的(匹配是在運行時進行的,包括cflow切入點類型)切入點定義指派特定的通知,而每個切入點可以與一條或多條通知關(guān)聯(lián)在一起。所支持的通知類型有幾種:環(huán)繞通知(around advice),前通知(before advice),返回后通知(after returning advice),拋出異常后通知(after throwing advice),以及引入通知(introduction advice)。本文稍后將給出環(huán)繞通知的一個例子。想要了解更詳細的信息,可以參考Spring AOP框架文檔。

正如先前提到的那樣,只可以通知由Spring IoC容器托管的目標對象。然而,在J2EE應(yīng)用程序中,組件的生命周期是由應(yīng)用服務(wù)器托管的,而且根據(jù)集成類型,可以使用一種常見的端點類型把J2EE應(yīng)用程序組件公開給遠程或本地的客戶端:

◆無狀態(tài)的、有狀態(tài)的或?qū)嶓wbean,本地的或遠程的(基于RMI-IIOP)

◆監(jiān)聽本地或外部JMS隊列和主題或入站JCA端點的消息驅(qū)動bean(MDB)

◆Servlet(包括Struts或其他終端用戶UI框架、XML-RPC和基于SOAP的接口)

J2EE中使用Spring AOP框架和EJB組件(1)498)this.style.width=498;" />

圖1:常見的端點類型

要在這些端點上使用Spring的AOP框架,必須把所有的業(yè)務(wù)邏輯轉(zhuǎn)移到Spring托管的bean中,然后使用服務(wù)器托管的組件來委托調(diào)用,或者定義事務(wù)劃分和安全上下文。雖然本文不討論事務(wù)方面的問題,但是可以在“參考資料”部分中找到相關(guān)文章。

我將詳細介紹如何重構(gòu)J2EE應(yīng)用程序以使用Spring功能。我們將使用XDoclet的基于JavaDoc的元數(shù)據(jù)來生成home和bean接口,以及EJB部署描述符??梢栽谙旅娴摹跋螺d”部分中找到本文中所有示例類的源代碼。

重構(gòu)EJB組件以使用Spring的EJB類

想像一個簡單的股票報價EJB組件,它返回當前的股票交易價格,并允許設(shè)置新的交易價格。這個例子用于說明同時使用Spring Framework與J2EE服務(wù)的各個集成方面和最佳實踐,而不是要展示如何編寫股票管理應(yīng)用程序。按照我們的要求,TradeManager業(yè)務(wù)接口應(yīng)該就是下面這個樣子:

public interface TradeManager {

public static String ID = "tradeManager";

public BigDecimal getPrice(String name);

public void setPrice(String name, BigDecimal price);

}

在設(shè)計J2EE應(yīng)用程序的過程中,通常使用遠程無狀態(tài)會話bean作為持久層中的外觀和實體bean。下面的TradeManager1Impl說明了無狀態(tài)會話bean中TradeManager接口的可能實現(xiàn)。注意,它使用了ServiceLocator來為本地的實體bean查找home接口。XDoclet注釋用于為EJB描述符聲明參數(shù)以及定義EJB組件的已公開方法。

/**

* @ejb.bean

* name="org.javatx.spring.aop.TradeManager1"

* type="Stateless"

* view-type="both"

* transaction-type="Container"

*

* @ejb.transaction type="NotSupported"

*

* @ejb.home

* remote-pattern="{0}Home"

* local-pattern="{0}LocalHome"

*

* @ejb.interface

* remote-pattern="{0}"

* local-pattern="{0}Local"

*/

public class TradeManager1Impl implements SessionBean, TradeManager {

private SessionContext ctx;

private TradeLocalHome tradeHome;



/**

* @ejb.interface-method view-type="both"

*/

public BigDecimal getPrice(String symbol) {

try {

return tradeHome.findByPrimaryKey(symbol).getPrice();

} catch(ObjectNotFoundException ex) {

return null;

} catch(FinderException ex) {

throw new EJBException("Unable to find symbol", ex);

}

}

/**

* @ejb.interface-method view-type="both"

*/

public void setPrice(String symbol, BigDecimal price) {

try {

try {

tradeHome.findByPrimaryKey(symbol).setPrice(price);

} catch(ObjectNotFoundException ex) {

tradeHome.create(symbol, price);

}

} catch(CreateException ex) {

throw new EJBException("Unable to create symbol", ex);

} catch(FinderException ex) {

throw new EJBException("Unable to find symbol", ex);

}

}

public void ejbCreate() throws EJBException {

tradeHome = ServiceLocator.getTradeLocalHome();

}

public void ejbActivate() throws EJBException, RemoteException {

}

public void ejbPassivate() throws EJBException, RemoteException {

}

public void ejbRemove() throws EJBException, RemoteException {

}

public void setSessionContext(SessionContext ctx) throws EJBException,

RemoteException {

this.ctx = ctx;

}

}

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI