【问题标题】:Share static singletons through EJB's通过 EJB 共享静态单例
【发布时间】:2009-01-30 22:35:33
【问题描述】:

我正在尝试在 Web 服务中创建缓存。为此,我创建了一个新的无状态 Bean 来将此缓存提供给其他无状态 bean。此缓存只是一个静态 ConcurrentMap,其中 MyObject 是一个 POJO。 问题是似乎有不同的缓存对象。一个用于客户端 bean,另一个用于本地。

-CacheService
-CacheServiceBean
  -getMyObject()
  -insertMyObject(MyObject)
  -size()

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

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

感谢您的回复。

【问题讨论】:

  • 感谢您的回复。一旦我可以测试你给我的不同答案,我就会用解决问题的答案来结束答案。一周,顶

标签: java jakarta-ee static singleton ejb


【解决方案1】:

据我所知,您无法确定无状态 bean 是否足够全局,可以让您将数据保存在静态字段中。有几个缓存框架可以帮助您解决这个问题。也许memcache

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

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

【讨论】:

    【解决方案2】:

    从表面上看,这似乎是一个矛盾的术语,因为缓存几乎可以肯定我不会认为是无状态的,至少在一般意义上。

    【讨论】:

    • 我也是这么想的!
    【解决方案3】:
    @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 方法级别这样做,您可能会更好地拥有一个同步的 Cache 对象(比方说,一个通用的 HashMap)。

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

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

    【讨论】:

      【解决方案4】:

      使用无状态 bean 时,您无法控制拥有多少实例(这取决于您的应用服务器来处理)。您可以从另一个 bean 获得输出,而不是您从客户端查找的那个。你把它打印在你的日志里了吗?在这种情况下,您可能应该看到不止一个输出。关键是,当您通过 jndi 查找无状态 bean 时,您无法知道您获得了哪个实例(您只获得了一个)。 而且,你没有状态,所以我不知道这是否是缓存的最佳选择。

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

      【讨论】:

        【解决方案5】:

        我知道这篇文章是不久前的,但似乎有一个新的 Singleton Bean 可以满足原始问题所针对的缓存需求:

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

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

        我尝试创建一个并从 WebService/Stateless bean 中引用它。像宣传的那样工作。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-09-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-03-18
          • 2010-10-21
          相关资源
          最近更新 更多