以下是来自Sun教程的摘录:
“..由于无状态会话bean可以支持多个客户端,因此它们可以为需要大量客户端的应用程序提供更好的可扩展性。”
无状态会话bean被用在哪里?什么样的应用程序会使用它?
在“无状态会话bean”出现之前,有哪些机制用于在类似的情况下支持多个客户端?
请问有人可以提供一些详细信息吗?
谢谢!
说实话,很难找到任何合理的 SLSB 使用场景。由于它们不保存任何状态(正如名称所示),它们应该天生就是线程安全的,即使容器对它们进行了池化。
另一方面,由于它们保证是线程安全的(多亏了池化),因此很容易将它们用作安全的临时存储,无需同步或线程安全集合。但是请考虑以下伪代码:
@Stateless
public class Slsb {
private int counter;
public void increment() {
++counter;
}
public int getCounter() {
return counter;
}
}
客户端:
@Resource
private Slsb slsb;
public void clientMethod() {
slsb.increment();
slsb.increment();
slsb.getCounter(); //???
}
这段代码(尽管有些粗俗)非常好,不需要例如AtomicInteger
之类的东西。
你期望什么结果?实际上,任何非负值都是可能的……任何对slsb
的调用都可能由Slsb
的不同实例提供服务,同时您(先前使用的)实例可能已被用于为不同的客户提供服务。结论:在SLSB中存储状态是错误的,但出于某种原因,SLSB被池化以避免线程问题(?!)。个人而言,我更喜欢单例服务(类似于Spring),从未理解过SLSB的想法。是的,我知道EJB 3.1中的单例EJB。
@Stateless
的主要目标。开发者仍然负责确保代表@Stateless
EJB的类没有声明任何实例变量(即没有状态)。容器不负责那部分。基本上,开发者必须说“嘿,容器,这是一个无状态业务服务类,我会用@Stateless
进行注释,以便您可以将其用作无状态EJB”,而不是反过来。@Stateful
,每次客户端获取它时都会重新创建(因此,如果客户端是例如视图范围的JSF托管bean,则EJB将随着该bean的存在而存在,或者如果客户端是例如会话范围的CDI托管bean,则EJB将随着该bean的存在而存在,等等)。或者,使用@Singleton
,它基本上是应用程序范围的并且实际上是线程锁定的。@Stateless
上的单个方法调用默认计为一个完整的事务。然而,该事务反过来需要在特定EJB实例上进行线程锁定,因为所有敏感的前处理和后处理工作都需要。因此,EJB基本上可以阻止所有其他客户端想要调用相同方法直到事务提交。这正是它们按需克隆和池化的原因。@Singleton
不是池化的,并且默认情况下实际上是线程锁定的。现在您应该明白,当(滥用)作为“无状态EJB”时,@Singleton
默认情况下绝对不比@Stateless
更快。另请参见Java EE 7教程“管理单例会话bean中的并发访问”。首先,无状态会话Bean(SLSB)是一种服务器端技术 - 比如你不会在Swing代码中使用它们。
但是,它们例如被用作许多连接到中央服务器的客户端的“Facade”。SLSB包含业务逻辑,可以调用数据库等操作。
由于SLSB可以进行池化,因此您不需要为每个客户端创建一个SLSB,而只需要为每个同时存在的客户端创建一个。当SLSB未被使用时,它将被放回池中,以便下一个客户端使用。
由于SLSB“托管”在容器中,因此它们是线程安全的,并且容器会为您处理大量重要的工作:事务、安全性、资源注入等等。
从非EJB技术特定的角度来看,无状态会话Bean是基础设施代码,显然不持有任何状态,但传递具有状态的对象。状态可以由您的有状态会话Bean或其他实现中的域POJO持有,而不是在EJB之外。如上所述,它是您业务层的入口点或门面。
在Java Web应用程序中,您可以按层设计,例如控制器、服务类(SLSB或仅为普通Java接口),然后是DAO或其他调用数据库/后端的内容。
EJB可以自动处理一些样板文件,例如事务、安全性等。