我们有一个遗留应用程序,现在我们在一个JVM中加载多个实例。我们现在在我们的新代码中使用Guice进行依赖注入,但现在是解决遗留应用程序代码的时候了。
遗留应用程序在许多线程中工作,这些线程是相当随机创建的(尽管所有线程都是通过帮助程序,所以我们可以在那里添加代码),我认为我们需要一个范围来覆盖该应用程序的每个实例。
那么,我应该创建自己的范围吗?我应该怎样覆盖多个线程?我可以使用应用程序的每个实例具有的唯一字符串,以便在每个线程的开头找到正确的范围吗?
答案 0 :(得分:1)
对范围的需求归结为一个问题:您是否希望能够为每个定义的环境注入完全相同的对象实例,但是它们在您定义的环境之间有所区别?< / em>(这意味着,对于对象Foo,那么每个遗留应用程序实例将接收不同的Foo,但是在该遗留应用程序实例的环境中,如果请求它,则总是会收到相同的Foo实例。如果是这样,那么范围就是你想要的。
关于范围的设计和实施,有两个重要的考虑因素:
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}},因此所有创建的对象都可以被垃圾收集。不要忘记将Scope实例本身绑定为单例(LegacyAppInstance
绑定必然是单例),这样你就可以从你的线程创建帮助器中获取它。