如果你仍然需要传递一个参数,那么依赖注入的重点是什么?

时间:2017-01-04 18:34:51

标签: scala dependency-injection playframework slick

我在理解依赖注入的基本思想时遇到了一些麻烦。 (我正在使用Play 2.5与play-slick模块)说我有一个需要数据库连接的类Users

package models

@Singleton
class Users @Inject() (dbConfigProvider: DatabaseConfigProvider) {

  private val db = dbConfigProvider.get[JdbcProfile].db

  private val users = TableQuery[UserTable]

  private val setupAction = DBIO.seq(users.schema.create)

  private val setupFuture: Future[Unit] = db.run(setupAction)

  def getAll(): Future[Seq[User]] = setupFuture.flatMap(_ =>
    db.run(users.result)
  )

  // More methods like the previous
}

当我有一个需要访问这些方法的视图时,我希望依赖注入系统为我填写dbConfigProvider依赖关系,就像这样。

package views

class UserSearch {

  def index(implicit ec: ExecutionContext): Future[String] = Future(
    (new Users).getAll().map(seq => seq.map(user => user.name).mkString(" "))
  )

}

然而,这给了我一个编译错误,我被迫使dbConfigProvider依赖于我的视图并明确地传递它。在这种情况下,我终于从调用该视图的控制器获取dbConfigProvider

package views

class UserSearch @Inject (dbConfigProvider: DatabaseConfigProvider) {

  def index(implicit ec: ExecutionContext): Future[String] = Future(
    (new Users(dbConfigProvider)).getAll().map(seq =>
      seq.map(user => user.name).mkString(" "))
  )

}

我假设我误解了依赖注入应该如何工作。

所以我的问题如下:

  1. 在我的模型@Inject()中使用Users关键字的重点是什么?

  2. 我的设计模式有缺陷吗?我希望UsersUserSearch成为对象,但我不能在它们上使用依赖注入。

  3. 如果有人熟悉Slick,我的getAll()方法是使用光滑的方法吗?这甚至是编写异步代码的正确方法吗?

2 个答案:

答案 0 :(得分:0)

DI的一个优点是易于使用其他实现,特别适用于可以在参数上传递模拟的测试。

例如,如果您收到将调用外部API的类(MyExternalClass)的实例,则可以发送一个子类(MyExternalSubClass extends MyExternalClass)来覆盖调用API的方法,并简单地返回一个预先配置的json

此处列出了一些优点(和缺点)(网上还有许多其他有趣的文章):

答案 1 :(得分:0)

感谢@MichaelZajac的评论,我将UserSearch改为声明为:

class UserSearch @Inject (users: Users)

现在我的控制器设置如下:

class UsersController @Inject()(userSearch: UserSearch) extends Controller {

  def index = Action.async {
    implicit request => userSearch.index().map(Ok(_))
  }

}

这直接回答了我的第一个问题,看到这个问题也回答了我的第二个问题。我现在收到SQL错误,但至少我的项目编译。我后来想出了我的第三个问题 - 结果是没有理由创建表格方案,因为在我的情况下它是由play evolutions文件完成的,因此我删除了setupFuture.flatMap部分,即使它可以正常工作它,并没有做任何愚蠢的事情,如创建表两次,或者在创建/启动表时可能需要做的其他事情。