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标准是在不断发展的,尤其是引入了异步和单例的并发控制方面。

也祝xmuzyu新年愉快,虎年大吉。

EJB3.0我还不是非常熟悉,3.1都出来了,只有更抓紧学习了。。。