我正在为一个web项目使用JSF 2.2,现在我正在实现登录页面。
我有一个login.xhtml
,用作视图,还有一个名为UserLoginView
的backingbean
这个bean有一个EJB
属性bean private UserService userService
(如这里所示)。
这是否意味着每一个新的UserLoginView
都会得到一个UserService
的新实例?
在生产环境中这样实现它可以吗?
这是否意味着每个新的UserLoginView都会获得一个新的UserService实例
没有。给定的UserService
是一个@Stateless
EJB。@Stateless
EJB作为容器自动生成的可序列化代理进行池化和注入。其中,EJB发生异常时的堆栈跟踪就是这方面的证据。您可以在backingbean方法和EJB方法之间看到额外的层。
@Stateless
EJB的自动生成代理类大致如下(实际上它更复杂,例如,根据EJB类和/或方法的@TransactionAttribute
,还需要在此处获取、启动和提交DB事务):
public class UserServiceProxy extends UserService implements Serializable {
public User find(Long id) {
UserService instance = getAnAvailableInstanceFromPool();
User result = instance.find(id);
releaseInstanceToPool(instance);
return result;
}
public Long save(User user) {
UserService instance = getAnAvailableInstanceFromPool();
Long result = instance.save(user);
releaseInstanceToPool(instance);
return result;
}
// ...
}
你看到了吗?它只是从EJB池中获取一个可用的实例,然后将方法调用委托给它,最后将它释放到池中以供将来重用。实际上正是这个代理实例被注入到JSF管理的bean中。
顺便说一句,CDI也是这样工作的。这正是为什么CDI可以在更宽范围的bean中注入更窄范围的bean,并且仍然使其按预期工作。JSF的@ManagedBean
注入了实际的实例,因此它不能以这种方式工作。如果JSF也使用代理,通过FacesContext
实际获取当前bean实例并委托给它,那么它就会起作用
实际上,只有@Stateful
EJB与客户端的生存期相关联。在托管bean作为客户端的情况下,它确实会得到"自己的"实例。另请参阅JSF请求范围的bean不断在每个请求上重新创建新的Stateful会话bean?
@Singleton
EJB在池中基本上最多有一个实例。因此,每个客户端将始终获得相同的实例。
在生产环境中这样实现它可以吗
当然。否则它们就不存在了。
小时>