使用@EJB 时,每个托管bean 是不是都有自己的@EJB 实例?

Posted

技术标签:

【中文标题】使用@EJB 时,每个托管bean 是不是都有自己的@EJB 实例?【英文标题】:When using @EJB, does each managed bean get its own @EJB instance?使用@EJB 时,每个托管bean 是否都有自己的@EJB 实例? 【发布时间】:2014-10-20 06:47:29 【问题描述】:

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

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

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

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

【问题讨论】:

【参考方案1】:

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

不。给定的UserService@Stateless EJB。 @Stateless EJB 被池化并作为容器自动生成的可序列化代理注入。其中,当 EJB 发生异常时的堆栈跟踪就是这方面的证据。您会看到支持 bean 方法和 EJB 方法之间的额外层。

@Stateless EJB 的自动生成代理类大致如下(实际上它更复杂,例如还需要在此处获取、启动和提交数据库事务,具体取决于 EJB 类的 @TransactionAttribute 和/或方法):

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 注入了 actual 实例,因此它不能那样工作。如果 JSF 也使用通过FacesContext 实际抓取当前 bean 实例并委托给它的代理,它会起作用。

只有@Stateful EJB 实际上与客户端的生命周期相关联。如果托管 bean 作为客户端,它确实会获得“它自己的”实例。另见JSF request scoped bean keeps recreating new Stateful session beans on every request?

@Singleton EJB 在池中基本上最多有一个实例。所以每个客户端总是会得到相同的实例。


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

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

【讨论】:

感谢您展示代理类的内部工作原理(对于 Java 开发来说也是非常新的,这些看起来都非常有用):)

以上是关于使用@EJB 时,每个托管bean 是不是都有自己的@EJB 实例?的主要内容,如果未能解决你的问题,请参考以下文章

sessionscoped 托管 bean 与有状态 ejb

结合 JPA、EJB 和 JSF 托管 bean 的首选设计模式是啥?

JSF 托管 bean EJB 注入

将 JSF2 托管 pojo bean 传递到 EJB 或将所需内容放入传输对象

沉淀再出发:Bean,JavaBean,POJO,VO,PO,EJB等名词的异同

每个 CLR 或每个进程是不是有一个托管堆?