亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

EJB 3.1 新特性介紹(一)

系統 1836 0

引言

Enterprise Java Beans(簡稱EJB)是Java Enterprise Edition(簡稱Java EE)平臺上的服務端組件架構模型,目標極力于快速并簡化分布式,事務處理,安全以及便攜式的應用程序。

EJB在其2.*時代也叱詫風云過,由于能夠解決許多企業應用程序的需求而被廣泛采納。但這只是EJB成功的表象,越來越多的質疑聲開始抨擊EJB的復雜。“缺乏好的持久層策略,又臭又長的布署描述符,能力有限的單元測試”等等這些常用卻又不好用的技術導致了大量開發人員開始尋找新的“輪子”。

Sun的反應的確有些遲鈍,但還是它花費大量精力來修訂規范,使得EJB得到很大的改觀。EJB3擯棄了許多現有的缺點,呈現給開發人員的解決方案在社區中大受好評。EJB又一次變成了切實可行的解決方案,并且現在已經有許多放棄它的團隊,再次接收EJB。

雖然它成功了,但EJB3還沒有當初預計的那么理想。反觀EJB2.1,新規范要面對兩個主要的挑戰:

1. 為了改變EJB2.1現有的特性, ( 比如說需要強大的持久層框架來代替 Entity Beans ;支持使用 Annotation 來代替布署描述符;拋棄 home interface 等等。 ) ,需要進行大量的重建工作。

2. 為了引入新的解決方案,需要加入原先規范中沒有的新技術。( 比如說支持 Singletons ;支持方法攔截;支持異步調用;改進并增強現有的 Timer Service 特性

對于EJB,優先考慮的就是全部重建。“我們只有先清空杯子里的水,才能接納新的東西”。現在杯子已經清空了,這對我們來說是非常有利的,而且還可以沒有包袱的大膽前進。

EJB3.1 又一次引入了一系列新的特性,傾向于挖掘技術的潛力。依我來看,EJB3.1絕對是一個重要的發布版本,它將那些長期讓人渴望的特性帶到開發者面前,更加能夠滿足最新的企業應用程序開發,同時對EJB再次被人們采納將做出巨大的貢獻。

近期,EJB 3.1提議最終草案已經發布了,現在我們已經非常接近最終發行版了。本文會貫穿大多數新的特性,對每一個新特性都有會有一定程度的介紹。

No-Interface View(非接口視圖)

EJB3.1引入了no-interface view的概念——將一個bean的所有的public method通過一個Local View暴露出來。 ( 具體訪問可見參見本文后面的 Global JNDI names ) Session Beans并不強迫你再去實現任何接口。EJB容器提供一個指向no-interface view的引用實現,允許客戶端調用該bean的任何public method,并且no-interface view也可以確保事務,安全以及攔截的行為與原先的用法一致。

通過non-interface view,所有bean的public method(當然也包括定義在其父類上的public method)都是可用的。一個客戶端可以通過依賴注入或JNDI lookup得到該view的引用,用起來感覺就好像它是local或remote的view一樣。

但與local和remote的view不同的是, local remote view 必須與其所實現的的業務接口同時存在 ,而no-interface view的引用則只是bean這個類本身。注意, no-interface view 不再依賴于接口

下面的代碼樣例說明了一個servlet使用no-interface view是一件多么容易事啊。這個被引用的no-interface view叫作ByeEJB,其實就是一個普普通通的JavaBean。該EJB并未實現任何接口,也沒有提供什么多余的布署描述符。最后但并不是最不重要的一點就是,這里EJB引用的獲得使用了依賴注入進行簡化。

Java代碼 收藏代碼
  1. ByeServlet
  2. (...)
  3. @EJB
  4. privateByeEJBbyeEJB;
  5. publicStringsayBye(){
  6. StringBuildersb=newStringBuilder();
  7. sb.append("<html><head>");
  8. sb.append("<title>ByeBye</title>");
  9. sb.append("</head><body>");
  10. sb.append("<h1>"+byeEJB.sayBye()+"</h1>");
  11. sb.append("</body></html>");
  12. returnsb.toString();
  13. }
  14. (...)
  15. ByeEJB
  16. @Stateless
  17. publicclassByeEJB{
  18. publicStringsayBye(){
  19. return"Bye!";
  20. }
  21. }

實際上如果引用類型為java類而不是接口的話,還是有些硬性的限制條件:

l 客戶端永遠無法使用new操作符來獲得引用。 ( 很明顯如果是你自己 new 出來的, EJB 容器自然無法托管 )

l 除了public method外,如果其它方法如果出錯,也會拋出EJBException異常。

l 一個指向該view的引用可以作為任何本地接口或其它no-interface view方法的參數進行傳遞或返回。

如果bean沒有暴露任何local或remote view,則容器必須默認提供一個可用的no-interface view。如果bean提供了至少一個local或remote view,則窗口不會提供no-interface view(除非使用@LocalBean顯式要求提供).

Bean和其父類的所有public method都會通過no-interface view被暴露出來。這也意味著任何public callback method也會暴露出來,因此在使用的時候要注意這一點。

本特性避免了接口的編寫,簡化了程序的開發(實際上并不是所有的類都需要接口)。也許在不久的將來還會加入remote no-interface view。

Singleton

大多數的應用程序都有過至少需要一個singleton bean ( 對每個應用程序來說,它意味著只需要初始化一次 ) 的經歷。許多供應商已經滿足了這方面的需求,通過使用描述布署符來限定一個bean所允許的最大實例數量。供應商這種“各自為政”的方式破壞了JAVA到處宣揚的“一次編寫,到處布署”的口號,因此迫切的再推出一套類似特性的規范來很有必要。EJB 3.1最終還是引入了singleton session beans。

現在主流的session beans有三類——stateless,stateful 和 singleton。Singleton session beans可通過使用Singleton Annotation來標注,然后每個應用程序會確保只實例化一次。Singleton session beans支持與客戶端共享,當然也支持并發訪問 ( 后面有會具體談到 )

singleton bean的生命周期始于容器下列任意初始化階段:

1. 直接實例化某個singleton

2. 通過依賴注入實例化某個singleton,這樣其依賴的那些singleton也會被跟著實例化,如此遞推下去。

3. 通過執行PostConstruct回調

缺省情況下,容器有義務決定singleton bean何時被創建 ( 比如在 spring 中,默認是將所有的 singleton 在啟動時就初始化 ) ,但是也允許開發人員使用Startup annotation在應用程序啟動時,要求容器去對singleton進行初始化。此外,Startup annotation還允許你去定義singleton beans之間的依賴關系。當容器開始處理任何客戶端發過來的請示時,所有標注有startup的singletons都必須初始化完成。

下面的代碼樣例大致演示了依賴是如何實現的。singleton A的沒有使用@Startup也沒有別的singleton依賴于它,于是A的實例化由容器來決定 ( 說白了,此時 A 的實例化由具體 EJB 實現來決定,規范沒有硬性規定 ) 。singleton B在應用程序啟動過程中被實例化,但必須早于singleton D和singleton E ( 很明顯,沒有 B 的實例, C D 可能都無法正常初始化 ) 。即使這個時候的B沒有使用@Startup,但由于有其它的singletons依賴于它,它還是要先實例化的。singleton C由于使用了@Startup,它會在應用程序啟動過程中被實例化,但必須比singleton E先完成。同理D也必須在E之前完成實例化。因此,E是應用程序中會最后一個被初始化。 ( 注意,再重申一下 A 是否會初始化與供應商的實現有關,也許供應商的實現是預先加載,也許是延遲加載,但當你真正使用 A 的時候,肯定會保證被初始化了 )

Java代碼 收藏代碼
  1. @Singleton
  2. publicclassA{(...)}
  3. @Singleton
  4. publicclassB{(...)}
  5. @Startup
  6. publicclassC{(...)}
  7. @Startup(DependsOn="B")
  8. @Singleton
  9. publicclassD{(...)}
  10. @Startup(DependsOn=({"C","D"})
  11. @Singleton
  12. publicclassE{(...)}

有一點需要注意的是,如果一個bean依賴于多個bean的注入,那么這些被依賴的beans之間的初始化時機是不確定的。E依賴于C和D,并沒有說C一定要在D之前被實例化,除非D本身也是依賴于C的。

singleton可以@Startup定義依賴于現存其它模塊中的singletons。

當應用程序關閉時,容器有義務執行singletons的PreDestory回調,將所有的singletons全部銷毀。這個時候,啟動時候的依賴關系在銷毀時變得有意義了,比如說A依賴于B,當A被銷毀時,B還是存活的,剛好與初始化相反。

Singleton bean會維護服務端與客戶端調用而產生的狀態,但當應用程序關閉或容器掛掉時,該狀態并不會保存下來。 ( 大家一定想到這種情況如果使用序列化機制將狀態保存下來,然后當程序再次啟動時,再反序列化還原狀態也是一種選擇。不過,至于你 singleton 中裝的是什么內容,是否需要被序列化,是否可以被序列化對容器來說還是未知數,所以干脆掛就掛吧。 ) 為了處理服務端與客戶端的并發調用問題,開發人員必須定義一個并發策略。規范中定義了兩種方式:

l CMC(Container-managed concurrency 容器托管的并發機制):顧名思義,由容器來管理該bean實例的并發調用。這也是EJB的默認策略。

l BMC(Bean-managed concurrency Bean托管的并發機制):容器此時并不會干涉該bean實例的并發,把并發的同步調用推回給開發人員。BMC允許使用合法的同步原語(如synchronized 和volatile關鍵字),來協調不同客戶端不同線程對同一個singleton的并發訪問。

( 呵呵,這不正是聲明式與編程式的又一次實踐嗎 ? )

大多數情況下,CMC肯定是首選。容器的管理并發問題時,還是使用“Lock (鎖)”。每個方法都關聯上一個read lock和write lock。Read lock表示應該方法可以盡可能的被多個線程并發調用,而write lock表示該方法在每次只能每一個線程訪問。

缺省情況下,lock的屬性值是write。當然你可以通過使用@Lock來修改默認屬性值。@Lock可以用于類,接口和方法。如其它Annotation類似,@Lock也有繼承性。在類級別使用@Lock,它的所有相關方法也會被應用上,除非你單獨限制某一個具體的方法。

當某個方法持有 write lock時,容器只允許其中一個并發線程去調用該方法。其它線程并必須等待,直到該方法再次變得可用。客戶端的等待也許是無限期的,這個時候可以使用@ AccessTimeout來指定一個最大等待時間。如果超時了,會拋出ConcurrentAccessTimeoutException異常。

下面的代碼示例中演示了如果使用CMC。Singleton A明確指定為CMC( 盡管這么沒有必要,因為默認就是 CMC ,主要還是為了演示 )。Singleton B并未定義任何并發策略,但按照規范,它還是屬性CMC范疇,它的所有方法顯示指定CMC使用 write lock方式。Singleton C與Singleton B幾乎一模一樣,只是使用的是read lock方式。Singleton D和Singleton C一樣,但是D中的sayBye方法重新定義為 write lock。Singleton E總要是演示@AccessTimeout的使用,當有因等待E中某方法而被阻塞的客戶端超過10秒時,就會招出ConcurrentAccessTimeoutException異常。

Java代碼 收藏代碼
  1. @Singleton
  2. @ConcurrencyManagement(CONTAINER)
  3. publicclassA{(...)}
  4. @Singleton
  5. @Lock(WRITE)
  6. publicclassB{(...)}
  7. @Singleton
  8. @Lock(READ)
  9. publicclassC{(...)}
  10. @Singleton
  11. @Lock(READ)
  12. publicclassD{
  13. (...)
  14. @Lock(WRITE)
  15. publicStringsayBye(){(...)}
  16. (...)
  17. }
  18. @Singleton
  19. @AccessTimeout(10000)
  20. publicclassE{(...)}

如果是在集群環境下,當應用程序布署在不同的JVM上,則每個JVM都有該singleton的一個實例。

直到EJB 3,任何由EJB拋出系統異常都會導致實例被廢棄和銷毀。但這個原則并不適用于singleton beans——它們必須一直存活下來,至少應用程關閉時才銷毀。因此任何在業務對像方法或回調拋出系統異常時,業務對象并不會被銷毀。

與 stateless beans一樣,singletons也可以暴露成web services。

Asynchronous Invocations( 異步調用 )

Session beans方法的異步調用是這些新特性中最重要的特性之一。它可以應用于所有類型的session beans。規范規定:在容器開始執行某個bean實例的調用之前,異步調用的控制權一定要返回給客戶端。這又將session beans提高到了一個嶄新的高度——使有潛在異步調用需求開發人員從session beans中獲得更多好處,也允許客戶端觸發并行處理的流程。

通過使用@Asynchronous就可以將一個類或方法標記為異步調用。下面的示例演示了該annotation不同場合下的應用。Bean A將其所有方法標注為異步;SingletonB中,只有定義的flushBye方法才是異步的;對stateless C而言,所有的通過local interface Clocal接口調用的方法都是異步的;而通過Cremote接口調用卻是同步的。因此,同一個方法還可能由于所引用的不同接口而表現出不同的行為。最后,bean D的flushBye肯定是異步的,于Dlocal是否是不是異步已經無關了。

Java代碼 收藏代碼
  1. @Stateless
  2. @Asynchronous
  3. publicclassA{(...)}
  4. @Singleton
  5. publicclassB{
  6. (...)
  7. @Asynchronous
  8. publicvoidflushBye(){(...)}
  9. (...)
  10. }
  11. @Stateless
  12. publicclassCimplementsCLocal,CRemote{
  13. publicvoidflushBye(){(...)}
  14. }
  15. @Local
  16. @Asynchronous
  17. publicinterfaceCLocal{
  18. publicvoidflushBye();
  19. }
  20. @Remote
  21. publicinterfaceCRemote{
  22. publicvoidflushBye();
  23. }
  24. @Stateless
  25. publicclassDimplementsDLocal{(...)}
  26. @Local
  27. publicinterfaceDLocal{
  28. (...)
  29. @Asynchronous
  30. publicvoidflushBye();
  31. (...)
  32. }

注意異步方法調用的返回類型必須是void或Future<V>(其中V表示返回值的類型)。如果方法的返回值為void,則不允許聲明任何應用程序異常。

Future接口在Java 5 中就被引入,提供四個主要方法:

  • cancel(booleanmayInterruptIfRunning):嘗試取消異步方法的執行。如果某個bean的實例方法還未開始調用,容器會嘗試取消這個調用。 如果為參數為 true:執行中的任務可以被interrupt;如果參數為false:允許這個任務執行完畢 。標志位“mayInterruptIfRunning”用于控制目標bean是否對客戶端是否可見,免得該異步調用被客戶端不小心給取消了。
  • get:當方法調用完成時,返回結果。該get方法有兩個重載版本,一個是調用后一直處于阻塞狀態,直到方法調用完成;另一個則可以設置一個超時的參數。
  • isCancelled:指示該方法是否被取消。
  • isDone:指示該方法是否執行完成。

規范要求容器提供AsyncResult<V>類作為Future<V>接口的實現,它可以將執行后的返回結構作為構造函數的參數,請看下面代碼:

Java代碼 收藏代碼
  1. @Asynchronous
  2. publicFuture<String>sayBye(){
  3. Stringbye=executeLongQuery();
  4. returnnewAsyncResult<String>(bye);
  5. }

Future<V>的返回類型因不同的客戶端角度而異。因此,如果在一個標有@Asynchronous

接口中定義了方法m,那么請注意,只有這個接口中的方法允許返回類型為Future<V>,在其它別的非異步接口中的定義中不能帶有Future<V>,只能返回普通的V( 注意 V 在這里表示的是泛型 )。請看下面示例:

Java代碼 收藏代碼
  1. @Stateless
  2. publicclassByeEJBimplementsByeLocal,ByeRemote{
  3. publicStringsayBye(){(...)}
  4. }
  5. @Local
  6. @Asynchronous
  7. publicinterfacesayBye{
  8. publicFuture<String>flushBye();
  9. }
  10. @Remote
  11. publicinterfaceByeRemote{
  12. publicStringsayBye();
  13. }

SessionContext接口有一個wasCancelCalled方法,用于判斷客戶端是否調用了Future和cancel方法。如果Future的cancel方法的mayInterruptIfRunning參數設置為true,那么wasCancelCalled自然也會返回true,也就是說異步調用被終止了。( 也就是說 SessionContext 可以用于判斷某個異步方法是否被取消,提高程序的健壯性 )。請看代碼示例:

Java代碼 收藏代碼
  1. @Resource
  2. SessionContextctx;
  3. @Asynchronous
  4. publicFuture<String>sayBye(){
  5. Stringbye=executeFirstLongQuery();
  6. if(!ctx.wasCancelCalled()){
  7. bye+=executeSecondLongQuery();
  8. }
  9. returnnewAsyncResult<String>(bye);
  10. }

( 下面代碼似乎有筆誤,根本無法通過編譯 )

如果異步方法拋出了一個普通應用程序異常,則這個異常傳播到客戶端時必須為ExecutionException。原始的異常信息仍然可以通過調用getCause來獲得的。

Java代碼 收藏代碼
  1. @Stateless
  2. publicclassByeEJBimplementsByeLocal{
  3. publicStringsayBye()throwsMyException{
  4. thrownewMyException();
  5. }
  6. }
  7. @Local
  8. @Asynchronous
  9. publicinterfaceByeLocal{
  10. publicFuture<String>sayBye();
  11. }
  12. //Client
  13. @Stateless
  14. publicclassClientEJB{
  15. @EJB
  16. ByeLocalbyeEjb;
  17. publicvoidinvokeSayBye(){
  18. try{
  19. Future<String>futStr=byeEjb.sayBye();
  20. }catch(ExecutionExceptionee){
  21. StringoriginalMsg=ee.getCause().getMessage();
  22. System.out.println("Originalerrormessage:"+originalMsg);
  23. }
  24. }
  25. }

對于異步方法的執行,客戶端的事務上下文并不會傳播到。因此,當下列異步事務方法調用時,可以得到的結論分別為:

  • 如果方法m的事務屬性定義為“REQUIRED”,那么它的表現形式將永遠為“REQUIRES_NEW”。
  • 如果方法m的事務屬性定義為“MANDATORY”,那么它的表現形式永遠是拋出TransactionRequiredException異常。
  • 如果方法m的事務屬性定義為“SUPPORTS”,那么它的表現形式永遠是不會參與在事務上下文中。

EJB 3.1 新特性介紹(一)


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产精品福利资源在线 | 免费一级特黄 | 欧美日韩免费在线视频 | 中文字幕欧美日韩久久 | 黑人和黑人激情一级毛片 | 综合久久网 | 激情五月婷婷红人馆 | 婷婷综合国产激情在线 | 看a网址| 亚洲va欧美va国产综合久久 | 精品欧美在线精品 | 久久精品网址 | 四虎国产永久在线精品免费观看 | 精品亚洲视频在线观看 | 手机看片欧美 | 欧美日本在线播放 | 黄频免费观看 | 欧美亚洲桃花综合 | 国产欧美在线播放 | 国产日韩欧美综合一区二区三区 | 性做久久| 久久免费在线 | 天天综合天天看夜夜添狠狠玩 | www.精品视频| 久久天堂 | 二级毛片免费观看全程 | 日日夜夜国产 | 最近在线更新中文字幕1 | 看欧美的一级毛片 | 91在线免费观看网站 | 青草国产精品久久久久久 | 国产伦精品一区二区三区无广告 | 四虎 在线播放 | 欧美日韩亚毛片免费观看 | 欧美白人猛性xxxxx交69 | 日韩欧美成末人一区二区三区 | 色综合久久中文综合网 | 高清亚洲 | 波多野结衣绝顶大高潮 | 老子影院午夜伦不卡亚洲 | 成人毛片免费视频播放 |