代码之家  ›  专栏  ›  技术社区  ›  Eldelshell

通过EJB共享静态单例

  •  1
  • Eldelshell  · 技术社区  · 16 年前

    我正在尝试在Web服务中创建缓存。为此,我创建了一个新的无状态Bean,以将此缓存提供给其他无状态Bean。此缓存只是一个静态ConcurrentMap,其中MyObject是POJO。

    -CacheService
    -CacheServiceBean
      -getMyObject()
      -insertMyObject(MyObject)
      -size()
    
    -SomeOtherBean
     cache = jndiLookup(CacheService)
     cache.insertMyObject(x)
     cache.size() -> 1
    

    在这个赋值之后,如果我从CacheServiceBean内部调用cache.size,我得到0。 甚至可以通过bean共享静态单例吗?最后,我决定使用一个数据库表,但我仍在考虑这个问题。

    5 回复  |  直到 16 年前
        1
  •  4
  •   svrist    16 年前

    据我所知,您不能确定无状态bean是否足够全局,以便您将数据保存在静态字段中。有几种缓存框架可以帮助您实现这一点。大概 memcache ?

    编辑: http://java.sun.com/blueprints/qanda/ejb_tier/restrictions.html#static_fields 说:

    非最终静态类字段为 在EJB中不允许,因为这样的字段 使企业bean变得困难或困难 无法分发

        2
  •  3
  •   Ben Hardy    16 年前

    从表面上看,这似乎是矛盾的,因为缓存几乎肯定是我不会考虑无状态的,至少在一般意义上是这样。

        3
  •  2
  •   Will Hartung    16 年前
    @Stateless
    public class CacheSessionBean implements CacheSessionLocal {
        private static Map<String, Object> cacheMap = new HashMap<String, Object>();
    
        public Object getCache(String key) {
            return cacheMap.get(key);
        }
    
        public void putCache(String key, Object o) {
            cacheMap.put(key, o);
        }
    }
    

    关于集群中EJB分布的警告适用于静态变量。然而,如果您不使用集群,它们几乎不适用于您,因此在这个级别上,静态是“好的”。

    缓解这种情况的一种方法是将容器配置为仅创建和池化CacheSession bean的单个实例,然后容器将为您管理该同步。

    您也可以自己管理同步,但不应该在EJB方法级别这样做,相反,使用同步缓存对象(例如,与通用HashMap相比)可能会更好。

    但关键是在这一点上,静态变量只是静态变量。

    从理论上讲,您需要了解会话Bean的容器生命周期(因为它可能会释放所有实例,因此实际的Bean类可能符合GC的条件,从而可能会丢失任何静态数据)。然而,在实践中,如果这项服务很受欢迎,这种情况就不太可能发生。但是,仅供参考,这是可能发生的。

        4
  •  1
  •   Yngve Sneen Lindal    16 年前

    使用无状态bean时,您无法控制它们的实例数量(这取决于您的应用程序服务器)。您可以从另一个bean获得输出,而不是从客户机中查找的bean。你在日志上写了吗?在这种情况下,您可能应该看到多个输出。关键是,当您通过jndi查找无状态bean时,您无法知道您得到了哪个实例(您只得到了一个实例)。

    静态单例我想你指的是单例对象? 是的,通过多个bean访问单例应该不会有问题。但是请记住您可能会遇到的并发问题。应用服务器(一般来说是bean)从您那里提取了很多内容。

        5
  •  1
  •   simgineer    13 年前

    我知道这篇文章是很久以前的事了,但似乎有一个新的单例Bean可以满足缓存的需要。最初的问题是:

    http://download.oracle.com/javaee/6/tutorial/doc/gipjg.html

    单例会话bean提供了与无状态会话bean类似的功能,但与之不同的是,每个应用程序只有一个单例会话bean,而不是一个无状态会话bean池,其中任何一个都可以响应客户端请求。与无状态会话bean一样,单例会话bean可以实现web服务端点。