天天看點

JavaEE 6:EJB3.1新特性

首先,祝各位道友春節愉快,虎年大吉,同時祝和我一樣的本命年的兄弟姐們虎年行好運,也祝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标準是在不斷發展的,尤其是引入了 異步和單例的并發控制方面。