使用@EJB 时,每个托管 bean 是否都有自己的 @EJB 实例? [英] When using @EJB, does each managed bean get its own @EJB instance?

查看:19
本文介绍了使用@EJB 时,每个托管 bean 是否都有自己的 @EJB 实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将 JSF 2.2 用于 Web 项目,并且我现在正在实施登录页面.

I am using JSF 2.2 for a web project and I am implementing the login page now.

我有一个 login.xhtml 用作视图,以及一个名为 UserLoginView 的支持 bean.
这个 bean 有一个 EJB 属性 bean private UserService userService(如图所示 此处).

I have a login.xhtml that serves as the view, and a backing bean called UserLoginView.
This bean has an EJB property bean private UserService userService (as shown here).

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

Does this mean that each new UserLoginView gets a new instance of UserService?

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

Is OK to implement it like this in a production environment?

推荐答案

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

没有.给定的 UserService 是一个 @Stateless EJB.@Stateless EJB 被池化并作为容器自动生成的可序列化代理注入.EJB 发生异常时的堆栈跟踪就是证明这一点的证据之一.您会在支持 bean 方法和 EJB 方法之间看到额外的层.

Nope. The given UserService is a @Stateless EJB. @Stateless EJBs are pooled and injected as serializable proxies autogenerated by the container. Among others the stack trace when an exception occurs from an EJB is evidence for this. You see extra layers between the backing bean method and the EJB method.

@Stateless EJB 的自动生成代理类大致是这样的(实际上它更复杂,例如 DB 事务也需要根据 @@EJB 类和/或方法的 TransactionAttribute:

The autogenerated proxy class for a @Stateless EJB looks roughly like this (in reality it's more complex, e.g. DB transaction also needs to be obtained, started and committed here depending on the @TransactionAttribute of the EJB class and/or method):

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 中.

Do you see it? It just grabs an available instance from the EJB pool and then delegates the method call to it and finally releases it to the pool for future reuse. It's exactly this proxy instance which is actually being injected in your JSF managed bean.

顺便说一下,CDI 也是这样工作的.这正是为什么使用 CDI 可以将范围较窄的 bean 注入范围较广的 bean 中,并且仍然使其按预期工作的原因.JSF 的 @ManagedBean 注入了 actual 实例,因此它不能那样工作.如果 JSF 还使用通过 FacesContext 实际获取当前 bean 实例并委托给它的代理,它会起作用.

CDI works also this way by the way. That's exactly why it's with CDI possible to inject a bean of a narrower scope in a bean of a wider scope and still get it to work as intented. JSF's @ManagedBean injects the actual instance and therefore it doesn't work that way. It would have worked if JSF also used proxies which actually grabbed the current bean instance via FacesContext and delegated to it.

只有 @Stateful EJB 实际上与客户端的生命周期相关.在托管 bean 作为客户端的情况下,它确实会获得自己的"实例.另见 JSF 请求范围bean 在每次请求时不断重新创建新的有状态会话 bean?

Only @Stateful EJBs are actually tied to the lifetime of the client. In case of managed bean as client, it would indeed get "its own" instance. See also JSF request scoped bean keeps recreating new Stateful session beans on every request?

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

And @Singleton EJBs have basically a maximum of one instance in the pool. So each client will always get the same instance.

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

绝对的.否则它们就不存在了.

Absolutely. Otherwise they didn't exist.

这篇关于使用@EJB 时,每个托管 bean 是否都有自己的 @EJB 实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆