确保模块在Guice中只加载一次



必须处理Guice,我想知道应该如何处理模块方面的依赖关系。

在Guice中,每个模块都由一个实例提供。因此,如果我有一个模块需要某个服务,它会创建一个模块,为该服务添加绑定并安装它(binder.install(module))

现在我有两个独立的模块,它们完全可以独立使用,并且都安装了相同的数据库模块。

独立使用两个模块不会出现问题,但如果两个模块都在同一应用程序中使用,会发生什么?数据库模块将由两个模块独立加载,这是不正确的。

有没有一种方法可以询问活页夹某个类型是否已经有了活页夹?我不能使用getProvider来检查这一点,因为无论某个东西是否已经绑定,返回的都是LookupProvider。

那么,如何应对这种情况呢?

更新:

它接缝Guice无法提供以下功能:

  1. 检查给定模块是否已加载
  2. 检查给定的类是否已绑定
  3. 使用配置中的提供程序可以进行分布式配置(能够配置所贡献对象的模块)

Guice有两个特性可以处理这种情况。第一个是模块重复数据消除。这意味着,如果安装了两个等效的模块(通过equals()hashCode()),则只有一个模块的configure()方法将运行。然而,这种解决方案有些脆弱,因为它无法通过SPI转换、Modules.override()

第二个也是IMO更好的解决方案是绑定重复数据消除。这意味着Guice将接受完全重复的绑定。因此,如果您的模块执行bind(Interface.class).to(Implementation.class),那么它的configure()方法是否运行两次都无关紧要,因为Guice可以很好地处理重复绑定。

由于Guice不支持某些所需的功能,因此必须对其进行模拟。multibinder代码提供了一个想法。我目前使用的另一个想法是在注射器构建过程中使用反射来找到最上面的粘合剂。知道了这个活页夹,就可以很容易地添加所需的元信息并跟踪某些对象。

一旦构建过程完成,这些元信息将被删除。

通常一次只构建一个注射器,但为了确保我们应该对此进行保护。

因此,请查看单个最多Binder的实现(RecordingBinder)。它提供了一个字段父级,我们可以步行到根绑定器元素。通常,Guice会使用一个最多的活页夹,但在私有模块的情况下。

另一个不那么安全但没有反射的想法是,如果您可以确保一次只构建一个Guice注入器,那么就使用线程本地。

能够识别构建过程并跟踪一次使用哪些构建器,就可以将任何类型的附加逻辑添加到指导中,比如防止两次安装依赖项。

绑定重复数据消除似乎已添加到Guice 4.0 中

https://github.com/google/guice/commit/c34e0185fcf508a890c6cd13bdafeb505c3e9e8a

最新更新