使用@EJB时,每个托管bean是否都会获得自己的@EJB实例



我正在为一个web项目使用JSF 2.2,现在我正在实现登录页面。

我有一个login.xhtml,用作视图,还有一个名为UserLoginView的backingbean
这个bean有一个EJB属性bean private UserService userService(如这里所示)。

这是否意味着每一个新的UserLoginView都会得到一个UserService的新实例?

在生产环境中这样实现它可以吗?

这是否意味着每个新的UserLoginView都会获得一个新的UserService实例

没有。给定的UserService是一个@StatelessEJB。@StatelessEJB作为容器自动生成的可序列化代理进行池化和注入。其中,EJB发生异常时的堆栈跟踪就是这方面的证据。您可以在backingbean方法和EJB方法之间看到额外的层。

@StatelessEJB的自动生成代理类大致如下(实际上它更复杂,例如,根据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在池中基本上最多有一个实例。因此,每个客户端将始终获得相同的实例。

<小时>

在生产环境中这样实现它可以吗

当然。否则它们就不存在了。

最新更新