具有缓存的EJB服务定位器

alt*_*fox 3 java ejb java-ee service-locator

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

我担心的是:

  1. 由于使用了相同的实例,因此不会使用服务器EJB池来处理多个EJB的多个并发请求(除非底层服务器逻辑以某种方式使用EJB池)
  2. 无状态和有状态EJB是线程安全的,但是由于每个EJB类只使用一个实例,并且EJB通过@PersistenceContext注入了EntityManager,我认为这意味着多个线程可以使用相同的EntityManager实例(而不仅仅是持久性) context),绝对不是线程安全的

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

Gab*_*uru 5

您从查找操作(通过JNDI服务)获得的是一个名为Stub的对象,并且他没有使用任何特殊的EJB实例进行修复.

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

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

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

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


关于你的评论:

如果你在一个由多个并发线程(如Servlet)使用的组件中使用EntityManager,是的,你将不得不关心并发性,但EJB的Tread模型意味着不会同时使用同一个EntityManager实例的多个线程因此EM不是线程安全的事实并不重要.

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

我认为,对于简单的风景最好的方式来想想,如果是形容这里:

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

这将更难检查;)