6

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

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

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

自定义范围 Guice wiki 中的类还使用成员变量SimpleScope提供了每个线程的实现。ThreadLocal<Map<Key<?>, Object>>

有了这个序言,我的问题是:如何创建一个非基于线程的作用域?似乎我可以用来查找 aMap<Key<?>, Object>的东西丢失了,因为传入的唯一东西Scope.scope()是 aKey<T>和 a Provider<T>

在此先感谢您的时间。

4

1 回答 1

7

有点不清楚您想要什么 - 您不想要基于线程的范围,也不想要忽略线程的范围。

但是,是的,范围旨在管理对象的生命周期并说明何时应重用实例。所以你真的在问“除了‘总是使用同一个实例’、‘从不使用同一个实例’和‘根据当前线程的执行环境使用一个实例’之外,还有什么其他的可能性可以重用一个实例? ?”

这就是我想到的:

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