我应该如何/应该创建自己的Guice范围

时间:2015-11-27 20:40:37

标签: java guice

我们有一个遗留应用程序,现在我们在一个JVM中加载多个实例。我们现在在我们的新代码中使用Guice进行依赖注入,但现在是解决遗留应用程序代码的时候了。

遗留应用程序在许多线程中工作,这些线程是相当随机创建的(尽管所有线程都是通过帮助程序,所以我们可以在那里添加代码),我认为我们需要一个范围来覆盖该应用程序的每个实例。

那么,我应该创建自己的范围吗?我应该怎样覆盖多个线程?我可以使用应用程序的每个实例具有的唯一字符串,以便在每个线程的开头找到正确的范围吗?

1 个答案:

答案 0 :(得分:1)

对范围的需求归结为一个问题:您是否希望能够为每个定义的环境注入完全相同的对象实例,但是它们在您定义的环境之间有所区别?< / em>(这意味着,对于对象Foo,那么每个遗留应用程序实例将接收不同的Foo,但是在该遗留应用程序实例的环境中,如果请求它,则总是会收到相同的Foo实例。如果是这样,那么范围就是你想要的。

关于范围的设计和实施,有两个重要的考虑因素:

  1. 所有范围都实现为可能缓存的Provider包装器。
  2. 除了同步单例创建之外,Guice没有线程的内部概念。
  3. Singleton范围只是一个Provider-wrapper,它创建一次对象并保存它以永久返回。请求和会话范围仅确定当前请求或会话,包装提供程序以返回相同的实例或委托给内部提供程序以在必要时创建新的实例。对于未作用的对象或假设的DoNothingScope,不需要包装 - 每次都会获得一个新对象,就像普通的Provider一样。最后,重要的是,对于Guice的Custom Scopes页面上基于线程的范围示例,Scope只返回一个匿名内部提供程序,它检查ThreadLocal<Map<Key, Object>>以在需要时返回现有对象。

    您可以使用Custom Scopes示例作为起点,并进行以下更改:

    • 保留Map<LegacyAppInstance, Map<Key, Object>>,因为您正在关闭应用程序实例而非线程。您的独特字符串将同样适用于密钥,但我不太了解有关可访问性的详细信息。
    • 您还希望保留ThreadLocal<LegacyAppInstance>(或ThreadLocal<String>),这样您就可以随时确定从Thread到旧版应用实例的映射。
    • enter()exit()需要进行一些更改:您要创建一个enter(LegacyAppInstance),您可以从新线程调用以建立从线程到线程的链接LegacyAppInstance。您只需要调用exit来销毁该特定Map<Key, Object>的{​​{1}},因此所有创建的对象都可以被垃圾收集。
    • 除此之外,它只是一样:返回一个提供者 - 可能是一个匿名的内部提供者 - 确定你所在的线程,确定哪个LegacyAppInstance正在播放,然后返回一个现有实例或根据需要创建新实例。

    不要忘记将Scope实例本身绑定为单例(LegacyAppInstance绑定必然是单例),这样你就可以从你的线程创建帮助器中获取它。