JavaEE 6:EJB3.1新特性

xmuzyu發表於2010-02-19
首先,祝各位道友春節愉快,虎年大吉,同時祝和我一樣的本命年的兄弟姐們虎年行好運,也祝jdon越辦越好,當然如果沒有banq老師辛勤耕耘這一片技術沃土,我們這些技術愛好者平時就沒發牢騷的地方嘍,所以最後,感謝banq板橋老師的辛勤勞動。

今天早上起床後上熟悉的infoq.com看看技術界在新的一年有啥好玩的東東,突然發現了以下這篇文章:

Java EE6: EJB3.1 Is a Compelling Evolution

下面我說說對上面文章的核心內容以及自己的一些牢騷哈哈哈。。

呵呵 J2EE標準,不,應該是JAVAEE標準經過了數次變革發展到今天的5.0,那麼5到6的跳躍有什麼新的特性呢?讓我們來看看JAVAEE6.0中非常重要的EJB3.1規範的新特性:

1 Singleton(單例)

EJB3.1之前,Session bean被設計為單執行緒的模型,此模型要求同一時刻某一個bean的例項只能被一個執行緒使用,其中無狀態會話bean採用例項池,而有狀態會話bean採用啟用鈍化技術實現。

EJB3.1引入了註解@javax.ejb.Singleton,這個註解可以標註session bean為單例項的,類似與J2EE開源界的IOC容器的單例,但是EJB3.1中的單例區別於傳統開源界的單例的不同之處就是:這種單例的例項是可以有狀態的,以前我們都是將無狀態的組建作為單例,但是EJB3.1以後,有狀態的元件也可以宣告為單例,這就是EJB3.1引入的併發控制模型,可以透過註解@javax.ejb.ConcurrencyManagement(CONTAINER)將bean宣告為容器管理的併發,和傳統的事物管理一樣,EJB3.1也給了開發者靈活的選擇,開發者還可以透過@javax.ejb.ConcurrencyManagement(BEAN)進行bean管理的併發,在採用了bean管理的併發以後,還可以採用@javax.ejb.Lock(WRITE)對bean的方法或者類進行註解,這裡的lock註解其實類似於JAVA中read-write lock(讀寫鎖)。

比如有如下的bean:
	@javax.ejb.Lock(WRITE)
	public class ChatRoom { 
	
	   private java.util.Map<User,Collection<String>> userComments; 
	
	   @PostConstruct 
	   public void setup (){ 
	     userComments = new java.util.concurrent.ConcurrentHashMap<User,Collection<String>>(); 
	     /* ...*/
	   }
	   public void join(User usr){ /* ...*/ }
	   public void disconnect(User usr){  /* ...*/ }
	   public void say(String msg){ /* ...*/  }
	
	   @javax.ejb.Lock(READ)
	   public int getCountOfActiveUsers(){ /* ... run through the map and count ... */ } 
	}
	



說到這裡,我們來看看這種方式有什麼好處,我以前也常說,過分依賴資料庫必然導致伸縮性瓶頸,以前的單例的無狀態的技術服務或者技術元件,我們都將其申明為單例的,是因為它們沒有共享的狀態,沒有共享的狀態就執行緒安全的,因此可以單例多個執行緒同時訪問,但是此時的併發控制留給了資料庫事務來完成,表面上看起來好像我們的service沒有同步,好像沒有鎖的概念,但是底層的事務是肯定有鎖,而這個鎖一般都是透過底層資料庫來實現的,這樣當大併發的情況下,資料庫就會不堪重負而死翹翹喔。

EJB3.1採用的這種方式其實也是一種我所推崇的記憶體併發的實現,也是執行緒安全的另外一種實現(執行緒安全的實現:一種是不共享狀態,另外一種透過鎖來進行共享狀態的訪問),透過記憶體併發來控制併發訪問,讓資料庫事務只保證A,C,D就OK了。

2 EJB Timer

EJB從2.1版本就引入了定時的機制,但是一直到3.0,定時機制使用起來都不是很方便,比如要注入定時服務到bean中。EJB3.1引入了申明式的定時服務,看看以下程式碼是不是很方便?

	@javax.ejb.Singleton 
	public class ChatRoom {
	
	   private java.util.Map<User,Collection<String>> userComments;
	        
	   @javax.ejb.Schedule(minute="1", hour="*") 
	   public void cleanOutOldDataFromChatLogs() { 
	      /** ... not reprinting all the existing code ... */
	   }
	} 
	


以上程式碼中,將cleanOutOldDataFromChatLogs方法透過@javax.ejb.Schedule(minute="1", hour="*") 註釋,這樣就可以此方法定時的執行。

3 無介面的bean

EJB3.0要求bean至少實現一個介面,而EJB3.1的bean可以不需要介面。不過個人認為這個特性相比與3.0沒什麼吸引的地方,我個人還是習慣將實現和抽象分離,介面本來就是申明what的,而實現就是how,顯示的分離我個人認為還是比較好。

4 非同步的服務

呵呵終於看到一個非常重要但是被J2EE忽略好久的特性了。以前J2EE標準都是同步的API(當然了除了JMS),而EJB3.1引入非同步無疑打破了傳統的同步限制,可謂與時具進啊哈哈。好了,廢話不多說了,看看EJB3.1是如何引入非同步的。 EJB3.1引入了@javax.ejb.Asynchronous 註解,這個註解可以用於類或者方法,如果用於類或者介面,那麼類和介面所有的方法都是非同步的。一般情況下,非同步的方法應該與非同步之前的呼叫是松耦合的,一般返回void,而有時候我們也需要利用非同步之後的結果,那麼就需要java.util.Future<V>,呵呵,好了,我們來看段程式碼吧,看了大家就一目瞭然。

	public CarHotelAndAirLineBookingServiceBean implements CarHotelAndAirLineBookingService  {
	  @javax.ejb.Asynchronous  
	  public Future<BookingConfirmation> bookCarHotelAndAirLine( Car rental, Hotel hotel, AirLine airLine) { 
	    /**  ...  */
	   } 
	 }
	
	  //客戶端程式碼
	
	  public BookingAction { 
	
	        @javax.ejb.EJB  private  CarHotelAndAirLineBookingServiceBean bookingService; 
	
	        private Future<BookingConfirmation> confirmation;
	
	        public String makeRequest(){ 
	
	                Hotel hotelSelection = ... ;
	                Car rentalSelection = ... ;
	                AirLine airLineSelection = ... ; 
	
	                confirmation = bookingService.bookCarHotelAndAirLine(
	                    rentalSelection, hotelSelection, airLineSelection ) ; 
	                return "showConfirmationPending";
	        }
	
	        public Future<BookingConfirmation> getConfirmation(){ /* ... */ }
	
	        /* ... */
	}
	
	


呵呵看到這裡有沒有發現似曾相識,jdon框架在6.1版本就引入了非同步的方式,可謂超前超前標準的,可喜可賀啊。 呵呵,這也印證了JAVAEE的潛規則:官方標準永遠落後與事實的標準喔。

5 簡化的部署

EJB3.1之前,我們JAVAEE application都是打包成EAR包,而3.1容許我們將其打包為WAR包,WEB-INF/classes以及WEB-INF/lib目錄下的類或者jar中的技術元件,如果經過了企業級bean的註解,那麼就會變為EJB了。EJB3.1還提供了一個精簡的版本用於嵌入式的裝置中。


呵呵,總體來說,JAVAEE標準是在不斷髮展的,尤其是引入了非同步和單例的併發控制方面。

相關文章