Google guice,覆盖配置

Google guice, override configuration

我正在与 Guice 合作并遇到一个设计问题。我的应用程序包含几个模块:

myapp-persistence 必须有单例 HibernateSessionFactory。它是由 Hibernate 设计的。 没问题我可以用 Guice 解决它:

class MyAppPersistenceModule extends AbstractModule {

  override def configure(): Unit = {

    bind(classOf[SomeStuff])
    bind(classOf[ClientDao])
    bind(classOf[CustomerDao])
    bind(classOf[SessionFactory]).toProvider(classOf[HibernateSessionFactoryProvider]).asEagerSingleton()

  }

  @Provides
  def provideDatabaseConnectionConfiguration: DatabaseConnectionConfiguration = {
    DatabaseConnectionConfiguration.fromSysEnv
  }

}

DatabaseConnectionConfiguration 传递给该单例的问题。 myapp-persistence 模块并不关心如何获取该配置。现在它取自 sys 变量。

myapp-rest 是 play-app,它想从 application.conf 读取 conf 并使用 Guice 将其注入其他组件。 myapp-backend 的作用大致相同。

现在我把自己锁在

@Provides
  def provideDatabaseConnectionConfiguration: DatabaseConnectionConfiguration = {
    DatabaseConnectionConfiguration.fromSysEnv
  }

而且我不明白如何使 myapp-rest 和 myapp-backend 变得灵活和可配置。

UPD 根据回答,我是这样做的:

定义的特征

trait DbConfProvider {
  def dbConf: DbConf
}

单例工厂现在依赖于提供者:

class HibernateSessionFactoryProvider @Inject()(dbConfProvider: DbConfProvider) extends Provider[SessionFactory] {
}

myapp-persistence 模块公开 public 带有所有 public 持久化模块 DAO 的 guice 模块。

myapp-persistence 具有仅用于测试目的的模块。 myapp-persistence Injector 加载模块描述如下:

class MyAppPersistenceDbConfModule extends AbstractModule {

  override def configure(): Unit = {
    bind(classOf[DbConfProvider]).to(classOf[DbConfSysEnvProvider])
  }

}

DbConfSysEnvProvider 从系统环境中读取数据库连接设置。非生产用例。

Play 应用程序有它自己的 conf 机制。我已将我的自定义模块添加到应用程序配置文件中:

# play-specific config
play.modules.enabled += "common.components.MyAppPersistenceDbConfModule"
# public components from myapp-persistence module.
play.modules.enabled += "com.myapp.persistence.connection.PersistenceModule"

还有我的配置服务:

@Singleton
class ConfigurationService @Inject()(configuration: Configuration) extends DbConfProvider {
...}

我不是 Play 特定设置方面的专家,但通常可以通过以下方式之一解决此类设计问题:

  1. 无默认值。从上游模块(myapp-persistence)中移除DatabaseConnectionConfiguration的绑定,并在每个下游模块(myapp-backend,myapp-rest)中酌情定义。

  2. 默认并覆盖。像您一样保留 DatabaseConnectionConfiguration 的默认绑定,在那里实现最常见的配置策略。在需要时使用 Guice Modules.override(..) API 在下游模块中覆盖它。

  3. 实现跨模块的统一配置机制,不依赖于所使用的特定框架。 (例如 Bootique,它是建立在 Guice 上的……虽然还没有在 Play 中使用它)。

我个人更喜欢方法 #3,但在没有像 Bootique 这样的东西的情况下,#2 是一个很好的替代方法。