Playframework 2.4のRuntime DI

2015.07.07

Playframework 2.4でDIする

Playframework 2.4における最大の変更点といえば、DI(依存性注入)をデフォルトで使用できるようになったことだと思います。 ※JSR 330をベースに実装

Playでは静的なDIと動的なDI、どちらも使用できるようになっていますが、 今回は動的なDIの方法について紹介します。

動作環境

今回使用した動作環境は以下のとおりです。
* OS : MacOS X 10.9.4 * Java : 1.8.0_11 * Playframework : 2.4.2

サンプルアプリ作成

まずはactivatorコマンドをつかって、プロジェクトのひな形を作成します。 テンプレートの種類はplay-scalaにしましょう。

% activator new runtime-di-sample
・
・

runコマンドで起動確認できたら準備完了です。

プログラム修正

DIを使用するにはroutesGeneratorに「InjectedRoutesGenerator」が指定されている必要があるので まずはbuild.sbtを確認しましょう。

routesGenerator := InjectedRoutesGenerator

次に、DI対象のclass(とtrait)を定義します。

package samples

import javax.inject._
import play.api.inject._
import scala.concurrent._
import play.api._

trait Person {
  def write()
}

@Singleton
class Programmer extends Person {

  def write(): Unit = {
    Logger.debug("writing program!!!")
  }

}

ここではPersonというtraitを定義し、それを実装するProgrammerクラスを定義しました。 また、ここでは@Singletonというアノテーションを使用していますが、これを指定することで 対象のクラスが自動的にシングルトンになります。

次に、DIされるコンポーネントのバインド設定をします。 Playではモジュールを使用してカスタムバインディングの設定をするため、 下記のようなモジュールを作成します。

package modules

import samples._
import com.google.inject.AbstractModule
import play.api._

class HelloModule extends AbstractModule {
  def configure() = {

    bind(classOf[Person])
      .to(classOf[Programmer])
  }
}

ここではPersonトレイトにProgrammerクラスをバインドしてます。 モジュールを定義したら、conf/application.confでモジュールの設定を記述します。

play.modules.enabled += "modules.HelloModule"

これでアプリ起動時にモジュールがロードされます。

最後にコントローラでDIしましょう。 @Injectアノテーションで引数にPersonを指定します。

import samples._
import javax.inject.Inject
import play.api._
import play.api.mvc._

class Application @Inject()(p:Person) extends Controller {
  def index = Action {
    //DIされたオブジェクトを実行
    p.write()
    Ok(views.html.index("Your new application is ready."))
  }
}

アプリを起動してブラウザでアクセスしてみてください。 Person(実装はProgrammer)がDIされてメソッド実行できることがわかります。

まとめ

今回はPlay2.4のRuntime Dependency Injectionを試してみました。 ちなみにApplicationLoaderを使用して静的DIをする方法もこちらにあるので、ご確認ください。

参考サイトなど