Playframework データアクセスするRepositoryクラスのDependencyInjection

個人開発したアプリの宣伝
目的地が設定できる手帳のような使い心地のTODOアプリを公開しています。
Todo with Location

Todo with Location

  • Yoshiko Ichikawa
  • Productivity
  • Free

スポンサードリンク

PlayでAnornを使用していて、RepositoryクラスをDIした時のメモ。といってもAnormは関係ない。

Repositoryクラス

差し替え可能であること前提で抽象化するようtraitを用意しておく。


Trait
trait ShopRepositoryTrait {
  def withBegin():ShopRepository
  def getList():List[String]
  def add():Option[Long]
  def delete():Option[Int]
}


Repository

Anormを使用していれば、DatabaseはすでにDIコンテナに入っているはずなので、Databaseインスタンスをインジェクトできる。

class ShopRepository @Inject()(implicit db: Database)  extends ShopRepositoryTrait{

  implicit val connection = db.getConnection

  def withBegin():ShopRepository = ???
  def getList():List[String] = ???
  def add():Option[Long] = ???
  def delete():Option[Int] = ???
}

implicit val connection = db.getConnectionはAnormがimplicitとして引数をとるexecuteUpdateなどのメソッドがあるので、定義しておくと便利。


RepositoryのDIコンテナ登録

作成したShopRepositoryをDIコンテナに登録する。


コンテナ定義

app/Module.scala

import com.google.inject.AbstractModule
import models.{ShopRepository, ShopRepositoryTrait}
import play.api.{Configuration, Environment}

class Module( environment: Environment,
              configuration: Configuration
            ) extends AbstractModule{

  override def configure() = {
    bind(classOf[ShopRepositoryTrait]).to(classOf[ShopRepository])
  }
}


尚、今回はDatabaseインスタンスはinjectしたが、コンテナ登録時にコンストラクタで引数を与えたい場合は、

bind(classOf[ShopRepositoryTrait]).toInstance( new ShopRepository(YourArgs, ...) )

のようにして記述できる。


コンテナ定義の登録

conf/application.conf

play.modules.enabled += "Module"


Repositoryオブジェクトの注入

以下のようにして注入できる。

@Singleton
class HomeController @Inject()
  (controllerComponents: ControllerComponents, shopRepository: ShopRepositoryTrait)
  extends AbstractController(controllerComponents) {
}