我正在使用JSF 2.2进行Web项目,现在我正在实现登录页面。
我有一个login.xhtml
作为视图,还有一个名为UserLoginView
的支持bean。
这个bean有一个EJB
属性bean private UserService userService
(如图here所示)。
这是否意味着每个新的UserLoginView
都会获得UserService
的新实例?
可以在生产环境中像这样实现吗?
答案 0 :(得分:17)
这是否意味着每个新的UserLoginView都会获得UserService的新实例?
不。给定的UserService
是@Stateless
EJB。 @Stateless
将EJB汇集并注入由容器自动生成的可序列化代理。其中,EJB发生异常时的堆栈跟踪就是证据。您可以在backing bean方法和EJB方法之间看到额外的层。
@Stateless
EJB的自动生成代理类看起来大致如此(实际上它更复杂,例如数据库事务也需要在这里获取,启动和提交):
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 request scoped bean keeps recreating new Stateful session beans on every request?
可以在生产环境中像这样实现吗?
绝对。否则他们就不存在了。