我们正准备开始在我们的保险数据转换平台中使用 Guice,我遇到了一个有趣的场景,在 Guice 文档或我发现的任何帖子中似乎都没有直接解决。
我们的平台在几个重要领域使用封装上下文 (EC) 模式。例如,假设我们正在处理一组 10 个策略。每当我们开始处理新策略时,我们希望构造一个PolicyContext
对象并初始化诸如策略编号、状态和公司之类的属性。这PolicyContext
是转换过程中涉及的许多类的依赖项。
请注意,PolicyContext
(以及*Context
我们应用程序中的其他对象)是一个紧密关注特定域区域的值对象(代表基本的、普遍需要的策略信息)。我很想知道你们中的模式专家是否仍然认为这是一种反模式(正如 Misko Hevery 在http://misko.hevery.com/2008/07/18/break-the-law-中所讨论的那样of-demeter-is-like-looking-for-a-needle-in-the-haystack/ ) 尽管这些是纯粹的价值对象,当然不代表“厨房水槽”。</p>
目前,我们正在PolicyContext
以最糟糕的方式进行管理:我们有一个静态全局变量 , policyContext
,policyContext.initialize(String company, String state, String policyNum)
每当我们开始处理新策略时都会调用它。
我的目标是让 Guice 以架构上优化的方式管理这些上下文对象,以便从概念上讲,每当我们开始处理新策略时:
- 古斯弃旧
PolicyContext
。 - Guice使用来自数据库的参数构造了一个新的、不可变的
PolicyContext
(没有臭名昭著的初始化方法) 。company/state/policyNum
- Guice 将已经构建
PolicyContext
的注入到所有需要它的类中。
这是我的暂定方法:
- 创建一个自定义范围——类似于http://code.google.com/p/google-guice/wiki/CustomScopes上的 Guice 批处理范围示例——其中批处理的边界由外部确定。有了这个范围,我们开始处理一个新的策略,我们可以 1) 结束前一个“批次”并开始一个新的。问:为什么我不能完全按照上述 URL 中列出的方式使用 Guice 批处理范围示例?
由于
PolicyContext
没有依赖关系,我们将对所有构造函数参数使用 AssistedInject(这似乎有点奇怪)。假设我们采用这种方法并生成一个PolicyContextFactory
,那么在我们开始处理新策略的地方,我们将拥有如下代码:… scope.exit(); scope.enter(); @Inject private PolicyContextFactory policyContextFactory; policyContextFactory.create(company, state, policyNum); // the parameters come from a database record. // Note that we don’t need to actually store the created instance; it will be injected elsewhere into various class constructors. …
这看起来是最优的吗?我知道可能有更简单的方法(例如PolicyContext
,每当我们处理新策略时,创建一个新的特定注入器,这会有效地创建一个新的PolicyContext
)。然而,这是架构的核心方面,所以我真的不想妥协。
我知道,另一种选择是在这种情况下避免使用 DI,而只使用PolicyContextManager
具有单独create
和get
方法的静态类,其中前一种方法是丢弃当前PolicyContext
并创建/存储新方法的工厂,而后一种方法只需返回“活动” PolicyContext
)。但是我的代码最终会执行手动 DI,因为我将编写很多代码,例如methodThatNeedsPolicyContext(PolicyContextManager.get(), …)
. 由于我们无论如何都打算开始使用 Guice,因此这种方法似乎不是最佳的。
顺便说一句,对于那些试图深入了解 DI 的人,我强烈推荐 Dhanji Prasanna 的“依赖注入”。这本书专注于 Guice 和 Spring,绝对是必不可少的,因为它比我遇到的任何其他东西都要深入得多。
谢谢你的帮助!