4

我正在使用缓存javax.naming.Context#lookup调用结果的服务定位器实现,并将其映射到请求的 EJB 接口,因此第一个请求之后的所有后续请求(对于同一个 EJB)都返回缓存的实例。

我的担忧是:

  1. 由于使用了相同的实例,因此没有使用服务器 EJB 池,该池将同时为多个 EJB 的多个请求提供服务(除非底层服务器逻辑以某种方式使用 EJB 池)
  2. 无状态和有状态 EJB 是线程安全的,但同样,每个 EJB 类只使用一个实例,并且 EJB 通过 @PersistenceContext 注入了 EntityManager,我假设这意味着多个线程可以使用同一个 EntityManager 实例(不仅仅是持久性上下文),这绝对不是线程安全的

您是否认为最好不要在服务定位器中使用缓存,或者我对 EJB 行为的担忧是不合理的?

4

1 回答 1

5

您从查找操作(通过 JNDI 服务)中得到的是一个名为 Stub 的对象,并且他没有使用任何特殊的 EJB 实例来固定。

缓存后,每次调用 EJB 服务时,存根都能够从池中选择不同的 EJB 实例(这适用于无状态);即使在集群环境中,存根对象也能够从不同的服务器中选择一个 EJB 实例。

因此,缓存存根对象应该不是问题。

请注意,我说的是无状态,我认为缓存对有状态会话 bean 没有意义。

EJB 查找是一项耗时的操作,因此缓存提高了客户端性能。


关于您的评论:

如果您在由多个并发线程(如 Servlet)使用的组件中使用 EntityManager,是的,您将不得不关心并发性,但 EJB 的 Tread 模型暗示不会有多个线程同时使用同一个 EntityManager 实例,所以 EM 不是线程安全的事实并不重要。

让我担心的仍然是不同的 EJB 使用相同的注入(通过@PersistenceContext)EntityManager 实例

我认为对于简单的风景来说是最好的思考方式,如果如此所述:

多用户客户端/服务器应用程序中最常见的模式是 entitymanager-per-request。在这个模型中,来自客户端的请求被发送到服务器(JPA 持久层运行的地方),一个新的 EntityManager 被打开,所有的数据库操作都在这个工作单元中执行。一旦工作完成(并且已经准备好对客户端的响应),持久性上下文以及实体管理器对象都会被刷新和关闭。

这将更难以检查;)

于 2013-10-22T21:40:52.420 回答