Playframework 2.4のRuntime DI
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をする方法もこちらにあるので、ご確認ください。