【问题标题】:Inject DatabaseConfigProvider with macwire使用 macwire 注入 DatabaseConfigProvider
【发布时间】:2019-11-22 00:32:02
【问题描述】:

我已尝试将 Slick 添加到我的项目中

创建 RoomRepo 类

class RoomRepo @Inject() (dbConfigProvider: DatabaseConfigProvider)(implicit ec: ExecutionContext) extends HasDatabaseConfigProvider[JdbcProfile]{/**...*/}

注入它

class ChatEngine @Inject()(dbRoom: RoomRepo)(socketIO: SocketIO)(implicit mat: Materializer){/**...*/}

ChatEngine 加载了 ma​​cwire

trait MyApplication extends BuiltInComponents
  with AssetsComponents
  with SocketIOComponents {
  lazy val dbConfigProvider = wire[DatabaseConfigProvider.get[JdbcProfile]]
  lazy val dbRoom = wire[RoomRepo]
  lazy val chatEngine = wire[ChatEngine]
  lazy val engineIOController: EngineIOController = chatEngine.controller

  override lazy val router = {
    val prefix = "/"
    wire[_root_.router.Routes]
  }
  override lazy val httpFilters = Nil
}

然后我得到这个错误:

[错误] /MyApplicationLoader.scala:31:59: 类型 get 不是 对象 play.api.db.slick.DatabaseConfigProvider

[错误] 懒惰 val dbConfigProvider = 线[DatabaseConfigProvider.get[JdbcProfile]]

[错误] ^ [错误] /MyApplicationLoader.scala:32:25:找不到类型的值: [play.api.db.slick.DatabaseConfigProvider]

[错误] 懒惰 val dbRoom = wire[RoomRepo]

[错误] ^ [错误] /MyApplicationLoader.scala:33:29:找不到类型的值: [models.RoomRepo]

[错误] 懒 val chatEngine = wire[ChatEngine]

【问题讨论】:

    标签: scala playframework slick macwire


    【解决方案1】:

    play-slick 可以通过扩展SlickComponents 来通过MacWire 实现compile-time dependency injection

    如果您使用的是编译时 DI,您可以使用 slickApi.dbConfig(DbName(name)) 方法直接从 SlickApi 查询数据库配置。 play.api.db.slick.SlickComponents 提供对slickApi 的访问。

    像这样

    trait DatabaseComponents extends SlickComponents {
      implicit def ec: ExecutionContext
      lazy val dbConfig = slickApi.dbConfig[JdbcProfile](DbName("default"))
      lazy val roomRepo: RoomRepo = wire[RoomRepo]
    }
    

    注意DbName("default") 指的是来自application.conf 的default 数据库,例如

    slick.dbs.default.profile="slick.jdbc.H2Profile$"
    slick.dbs.default.db.profile="org.h2.Driver"
    slick.dbs.default.db.url="jdbc:h2:mem:play;DB_CLOSE_DELAY=-1"
    

    修改RoomRepo 以使用DatabaseConfig 而不是DatabaseConfigProvider 像这样

    class RoomRepo(dbConfig: DatabaseConfig[JdbcProfile]))(implicit ec: ExecutionContext) ...
    

    然后像这样混入DatabaseComponents

    trait MyApplication 
      extends BuiltInComponents
      with AssetsComponents
      with SocketIOComponents
      with DatabaseComponents {
    
      ...
      implicit val ec: ExecutionContext = scala.concurrent.ExecutionContext.Implicits.global
    }
    

    多说几句:

    • 我们可能不应该将@Inject 与 macwire 混合使用,因为前者用于运行时依赖注入,而后者用于编译时 DI。
    • wire 的签名是def wire[T]: T,其中T 必须是编译时解析的类型,而DatabaseConfigProvider.get[JdbcProfile] 是运行时值,因此wire[DatabaseConfigProvider.get[JdbcProfile]] 不会编译。

    【讨论】:

      猜你喜欢
      • 2016-06-10
      • 2015-03-08
      • 2017-12-06
      • 2018-08-30
      • 2018-06-04
      • 2017-01-16
      • 1970-01-01
      • 2020-09-11
      • 2018-07-17
      相关资源
      最近更新 更多