2013-10-22 82 views
4

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

我的担忧是:

  1. 由于相同的情况下被使用,不存在 服务器EJB池这将成为多个同时发生的请求 与多个EJB(除非底层服务器的逻辑不知何故使得利用 使用EJB池的)
  2. 无状态和有状态EJB是线程安全的,但由于再次使用 只有每个EJB类一个实例,EJB拥有的EntityManager 通过@PersistenceContext注入,我认为MEA NS多个 线程可以使用相同的EntityManager实例(不仅仅是 持久化上下文),这绝对不是线程安全的

你认为这是最好不要在服务定位器使用缓存,或我的担心对EJB行为是不合理的?

回答

5

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

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

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

请注意,我在谈论无状态,我认为缓存对有状态会话bean没有意义。

EJB查找是一个耗时的操作,所以缓存提高了客户端的性能。


关于您的评论:

如果您正在使用的EntityManager所使用的多个并发线程就像一个Servlet一个组件内,是的,你将不得不关心并发,但EJB的胎面模型暗示这不会是多个线程同时使用同一个EntityManager实例,所以EM不是线程安全的事实并不重要。

我关注的仍然是,不同的EJB使用 相同注射(通过@PersistenceContext)EntityManager实例

我认为,简单的风景最好的方式来想想,如果如描述here

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

这将更加难以遏制;)

+0

我已经证实了这一点,使用在相同的缓存实例与并行方法调用的测试 - 尽管参考EJB(存根如你所说)是一样的,调试确认实际的EJB是不同的。我关心的仍然是不同的EJB使用相同的注入(通过@PersistenceContext)EntityManager实例。我无法确认100%这是线程安全的(因为EntityManager本身不是线程安全的),但似乎合乎逻辑的是,由于它是容器管理的,它是 - 并且可能使用代理对象的相同原理来真正的新兴市场。 – alterfox