如何创建非基于线程的Guice自定义范围?

时间:2010-03-23 18:49:02

标签: scope guice

似乎所有Guice开箱即用的Scope实现本质上都是基于线程的(或完全忽略线程):

Scopes.SINGLETONScopes.NO_SCOPE忽略线程并且是边缘情况:全局范围,没有范围。

ServletScopes.REQUESTServletScopes.SESSION最终依赖于从ThreadLocal<Context>检索范围对象。检索到的Context包含对HttpServletRequest的引用,该引用包含对作为命名属性存储的作用域对象的引用(其中name源自com.google.inject.Key)。

来自自定义范围的

SimpleScope Guice wiki还使用ThreadLocal<Map<Key<?>, Object>>成员变量提供每线程实现。

有了这个序言,我的问题是:如何创建一个非基于线程的范围?似乎我可以用来查找Map<Key<?>, Object>的内容丢失,因为传递给Scope.scope()的唯一内容是Key<T>Provider<T>

提前感谢您的时间。

1 个答案:

答案 0 :(得分:7)

有点不清楚你想要什么 - 你不想要基于线程的作用域,并且你不想要忽略线程的作用域。

但是,是的,范围旨在管理对象的生命周期,并说明何时应该重用实例。所以你真的要问“除了'总是使用相同的实例','永远不要使用相同的实例',以及'根据当前线程的执行环境使用实例'时,重新使用实例的其他可能性是什么? ?“

以下是我想到的:

  • 在固定的时间内使用相同的实例。这里的示例是一个每十分钟重新加载和重新分析的配置文件。
  • 执行一些网络调用以查询是否应重新使用给定对象(可能是快速调用以确定是否需要重建对象,但重建对象的调用很慢)
  • 重复使用相同的对象,直到有人打电话告诉我们重新加载
  • 每个线程重用相同的对象,但不使用显式输入的范围,并像servlet范围一样离开。 (所以每个线程一个实例)
  • “此线程和子线程”范围基于InheritableThreadLocal,而不是普通ThreadLocal
  • 与此相关,Scope和基于线程池的ExecutorService工作,以便在线程和它提交的作业之间共享实例以供后台执行。
  • 将实例拉出池中;这很棘手,因为我们需要一个很好的方法来在完成后将对象返回池中。 (也许你可以将这个想法与请求范围结合起来,以便在请求结束时可以将对象返回到池中)
  • 组合两个或多个其他范围的范围,例如,我们可以获得一个每10分钟重新读取一次的配置对象,除了在给定请求的生命周期内使用相同的实例。