【发布时间】:2010-01-17 04:59:55
【问题描述】:
无状态会话 bean 不维护状态。那么这是否意味着它们不应该有实例变量?
谢谢,
罗杰
【问题讨论】:
标签: java jakarta-ee ejb-3.0
无状态会话 bean 不维护状态。那么这是否意味着它们不应该有实例变量?
谢谢,
罗杰
【问题讨论】:
标签: java jakarta-ee ejb-3.0
在这种情况下,术语“状态”有点误导。它指的是会话状态,这意味着如果客户端进行多次调用,会话 bean 无法知道。想象一下一系列调用:
reserveSeatsOnFlight();chooseMealPreference();confirmBooking()。你所拥有的是对话状态,这意味着第二次调用必须与第一次调用相同的 bean 进行,否则它就没有意义了。这就是有状态会话 bean 的作用。
无状态会话 bean 可以有实例变量,但它们本质上是全局的。如果您有一个无状态会话 bean 池(您可能会或可能不会取决于容器决定做什么),那么从一次调用到下一次调用,这些实例变量可能存在也可能不存在。所以一般要避免实例变量。这种事情还有其他机制。
让我举个例子。想象一下在无状态会话 bean 中的这个调用:
public void bookFlight(List<Passsenger> passengers, FlightNumber flight, Date date) {
...
}
如果您放入一个实例变量来计算预订数量并在每次调用时增加它,那么后续调用可能会调用不同的 bean,因此会看到不同的值。这就是我的意思,它不一定有意义。
回到第一个例子,处理这个问题的一种方法是将状态传回给调用者:
public interface ReservationSystem {
public int createNewBooking();
public int reserveSeatsOnFlight(int bookingId, int seats);
public int chooseMealPreference(int bookingId, ...)
...
}
看看上面的内容如何不再具有会话状态?确实如此,但它现在封装在您传递的bookingId 中。无状态会话 bean 可以检索预订并从另一个中断的地方继续。
【讨论】:
我经常看到无状态会话 bean 使用局部变量作为维护 bean 内“全局”状态的一种方式(以避免将数据从对象内的一个方法调用传递到另一个方法调用的繁重任务)。
话虽如此,这些本质上是您的对象中的全局变量,并且容易被滥用(因为它们在我见过的大多数情况下也是如此)。我倾向于建议避免使用它们。
在某些情况下它们可能很有用,但是……您有特定的用例吗?
【讨论】:
无状态 bean 可以像任何其他对象一样具有实例变量。它只是不能使用它们来维护特定于特定客户端的值......
【讨论】:
如何保存在 SLSB 启动时(即在构造函数中)初始化的 final 实例变量。 我正在考虑在 SLSB 的构造函数中实例化的 DAO 属性,如下所示:
@Stateless
public class MyStatelessBean() {
private final CustomerDAO customerDAO;
public MyStatelessBean() {
// Initialization code goes here
this.customerDAO = new CustomerDAO();
}
...
}
所以 DAO 可以直接在 SLSB 的方法中使用,而不必在每次需要 DAO 时都创建。当然,前提是 DAO 是无状态的,这通常是这种情况。与数据库的连接当然是按需提供的,并且永远不会存储在 SLSB 本身中。
【讨论】: