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) { }
リンク
リンク