初步学习了EJB3.0的一些知识,也通过建工程,配环境,部署等完成了一个EJB的小例子。在EJB中包括着三种Bean.会话bean(session bean)、实体bean(entity bean)、消息驱动bean(message-driven bean),下面我们就来主要介绍下这些Bean作用。
会话bean(session bean):负责与客户端交互,是编写业务逻辑的地方,在会话bean中通过操作实体bean来完成对数据库的操作。
会话bean分为两种:
无状态会话bean (Stateful Session Bean):平常使用最多的是无状态bean,因为它的bean实例可供多个用户使用,所以它的性能比有状态bean高。正因为一个bean实例被多个用户使用,那么前一个用户设置的值有可能被后一个用户所修改,所以它无法正确保存某个用户设置的值,因此是无状态的。
有状态会话bean (Stateless Session Bean):有状态会话bean在项目中我还没有使用过,因为它的一个bean实例只供一个用户使用,所以性能开销比较大,正因为它的实例只被一个用户使用,用户为它设置的值是不会被其他用户修改,所以可以正确保存用户设置的值,因此是有状态的。
当客户机和服务器建立连接之后,状态会话bean将一直在客户机和服务器之间保持着用户的某个状态。
实体bean(entity bean):它实际上属于java持久化规范(简称JPA)里的技术,JPA的出现主要是为了简化现有的持久化开发工作和整合ORM技术,结束现在Hibernate、TopLink等ORM框架各自为营的局面。
消息驱动bean(message-driven bean):它是专门用于异步处理java消息的组件,具有处理大量并发消息的能力。只有在需要一个JMS客户的时候才会实用消息驱���bean。换句话说,消息驱动 bean可以监听来自JMS消息服务的消息。客户绝对不会直接调用消息驱动bean;要想让消息驱动做点什么事情,客户必须向一个消息服务发出一条消息。这说明,消息驱动bean没有相应的EJBObject,因为服务器会从消息服务直接得到客户请求,而不是当客户向bean发出调用时截获客户请求。
在实际的工作中会话Bean用的最多,会话Bean有分为无状态和有状态的,那么这两者之间的区别是怎么样呢?我们在实际工作中应该选择那种合适的Bean呢?
那么我们来说说这两者之间的区别:
现实中,很多朋友对两种session bean存在误解,认为有状态是实例一直存在,保存每次调用后的状态,并对下一次调用起作用,而认为无状态是每次调用实例化一次,不保留用户信息。仔细分析并用实践检验后,你会发现,事实恰好相反:有状态和无状态会话bean的本质区别是它们的生命期。
首先解释一个下面要用到的概念--用户:session bean 的用户实际上就是直接调用ejb的类的实例,甚至是这个实例的某个方法。同一个类的不同实例对于session bean 来说是不同的用户。
在代码上有状态Bean和无状态Bean区别不大,但是却是用了Bean实例的两种管理技术,即:
1. 无状态bean使用实例池技术管理bean。 容器会创建一些bean的实例,等待客户使用,和数据库连接池原理类似。
2. 有状态bean使用激活(activation)管理bean。 不存在、创建bean、钝化、激活。
EJB引入了激活机制。激活机制实现的原理是这样的,在EJB服务器需要节省资源时,就从内存中收回bean实例,将其所保持的会话状态序列化到��盘中,并且释放其所占有的内存,这个过程为钝化。若此时客户端对EJB再次发起请求,EJB容器会重新实例化一个 Bean实例,并从硬盘中将之前的状态恢复,这叫做激活。
在实际用户调用来看,这两者就有着一些区别:
1.有状态会话bean :每个用户有自己特有的一个实例,在用户的生存期内,bean保持了用户的信息,即“有状态”;一旦用户灭亡(调用结束或实例结束),bean的生命期也告结束。即每个用户最初都会得到一个初始的bean。
2.无状态会话bean :bean一旦实例化就被加进会话池中,各个用户都可以共用。即使用户已经消亡,bean 的生命期也不一定结束,它可能依然存在于会话池中,供其他用户调用。由于没有特定的用户,那么也就不能保持某一用户的状态,所以叫无状态bean。但无状态会话bean 并非没有状态,如果它有自己的属性(变量),那么这些变量就会受到所有调用它的用户的影响,这是在实际应用中必须注意的。
区别的根本原因(这与无状态会话Bean和有状态会话Bean的运行原理是相关的。)
对于有状态会话Bean来说,只要有客户端发送对有状态会话Bean的访问,服务器都会创建一个会话Bean实例与该客户端对应,这样这个实例与这个客户端就是一一对应的。如果客户端在Bean实例中保存了信息,之后还可以使用。
对 于无状态会话Bean来说,服务器端会维持一个实例池,创建好若干个实例对象供客户端调用。当从客户端发送创建会话Bean的请求时,并不一定会真的创建 EJB,多数情况下是从实例池中得到一个实例,用完之后重新放回实例池。如果下次再访问,再从实例池中取出一个实例使用,并不一定是上次的实例。即使两次 访问使用的是同一个实例,在两次访问之间也有可能有其他的客户端访问了该实例。所以,并不能保证在多次访问之间的信息会被保存。所以,无状态会话Bean 不会专门保存客户端的信息。
各自的优缺点
因为有状态会话Bean需要保存特定客户端的信息,一个客户端对应一个实例,既是在当时客户端有连接没有访问的情况下,也要为这个客户端保留这个实例。这样随着客户端数量的增加,服务器端需要创建的实例的数量也在增加,增加到一定程度对服务器的性能就会有一定的影响。为了不对服务器的性能产生影响,通常服务 器会进行一些优化。当客户端的数量超过某个值之后,就不创建新的实例。虽然不创建新的实例,还是需要对用户响应,这时候就采用共享实例的方式。会查看哪个 实例虽然处于连接状态,但是没有访问,然后把这个实例的状态保存起来,使用这个实例为新的请求服务,对于原来的客户端来说,称为挂起。如果原来的客户端又 发送请求了,会重新查找一个空闲的实例并且把已经保存好的状态恢复回来,这个过程称为激活。所以在有状态会话Bean的访问过程,经常会发生查找实例,激 活挂起等操作,所以效率比较低。
而发送对无状态会话Bean的请求的时候,可以随便取一个空闲的实例为客户端服务,所以效率比较高。
有状态会话Bean的好处是,可以保存客户端的状态,所以客户端在后续访问的时候就可以少传递一些参数。而无状态会话Bean需要传递方法执行过程中需要的所有参数。
如何选择
��据上面分析的有状态会话Bean和无状态会话Bean的优缺点。如果要频繁的访问,并且多次访问之间会共享一些信息,这时候应该使用有状态会话Bean。对于不经常使用的功能,可以使用无状态会话Bean。无状态会话Bean的使用要比有状态会话Bean的使用多。
[转载]参考资料:http://blog.sina.com.cn/s/blog_59d6717c0100m9q5.html