§プラグインからモジュールへの移行
注記: 非推奨の
play.Plugin
システムは、2.5.xから削除されました。
Playプラグインを実装している場合は、非推奨のJava play.Plugin
またはScala play.api.Plugin
タイプではなく、play.api.inject.Module
を使用して実装を移行することを検討してください。
古いPlugin
APIと、Module
を使用する新しいAPIの主な違いは、後者では依存性注入(DI)を完全に採用することです。PlayがDIについて意見を持つようになった理由についてはこちらを参照してください。
§理由
古いPlugin
APIでは、ロードするプラグインの数と完全修飾名を含むplay.plugins
ファイルを提供する必要がありました。この数は、Playによってプラグイン間の合計順序を決定するために使用されました。このアプローチは、数が初期化順序の正しい場所に一致することを保証するのが難しいため、プラグインの依存関係がプラグインが初期化される前に初期化される可能性があり、脆かったです。さらに、2つのプラグインが同じ番号を使用することを回避する方法はありませんでした。DIを使用することで、これらの両方の問題が解決されました。コンポーネントは、コンストラクタ引数として依存関係を明示的に宣言し、コンストラクタで初期化を実行するようになりました。
§Module
クラスの作成
play.api.inject.Module
を継承するクラスを作成し、bindings
メソッドの実装を提供することから始めます。このメソッドでは、モジュールによって提供されるコンポーネントをユーザーのコードまたは他のモジュールに注入できるように、型を具体的な実装に接続する必要があります。次に例を示します。
Javaの場合
import play.api.Configuration;
import play.api.Environment;
import play.api.inject.Binding;
import play.api.inject.Module;
import scala.collection.Seq;
public class MyModule extends Module {
public Seq<Binding<?>> bindings(Environment environment, Configuration configuration) {
return seq(
bind(MyComponent.class).to(MyComponentImpl.class)
);
}
}
Scalaの場合
import play.api.Configuration
import play.api.Environment
class MyModule extends Module {
def bindings(environment: Environment, configuration: Configuration): Seq[Binding[_]] = {
Seq(
bind[MyComponent].to[MyComponentImpl]
)
}
}
定義しているコンポーネントが別のコンポーネントを必要とする場合は、@javax.inject.Inject
アノテーションをコンストラクタの前に付けることで、必要なコンポーネントをコンストラクタの依存関係として追加するだけで済みます。DIフレームワークがそれ以降の処理を行います。
注記: コンポーネントBがAを必要とする場合、BはAが初期化された後にのみ初期化されます。
次に、MyComponentImpl
という名前のコンポーネントがApplicationLifecycle
コンポーネントを必要とする例を示します。
Javaの場合
import javax.inject.Inject;
import play.inject.ApplicationLifecycle;
import play.libs.F;
public interface MyComponent {}
class MyComponentImpl implements MyComponent {
@Inject
public MyComponentImpl(ApplicationLifecycle lifecycle) {
// previous contents of Plugin.onStart
lifecycle.addStopHook( () -> {
// previous contents of Plugin.onStop
return F.Promise.pure(null);
});
}
}
Scalaの場合
import javax.inject.Inject
import scala.concurrent.Future
import play.api.inject.ApplicationLifecycle
trait MyComponent
class MyComponentImpl @Inject() (lifecycle: ApplicationLifecycle) extends MyComponent {
// previous contents of Plugin.onStart
lifecycle.addStopHook { () =>
// previous contents of Plugin.onStop
Future.successful(())
}
}
§接続
新しく作成したModule
クラスを有効なモジュールのセットに追加する時間です。これを行うには、設定ファイルに次の行を追加するだけです。
play.modules.enabled += "my.module.MyModule"
他のプロジェクト(サブプロジェクトを含む)で使用されるライブラリに取り組んでいる場合は、上記の行をreference.conf
ファイルに追加します(まだreference.conf
がない場合は、作成してsrc/main/resources
に配置します)。そうでない場合、エンドPlayプロジェクト内にある場合は、application.conf
内にある必要があります。
エンドPlayプロジェクトの場合は、`Module`という名前のクラスを作成し、ルートパッケージ(「app」ディレクトリ)に配置することもできます。
注記: ライブラリに取り組んでいる場合は、アプリケーションによってモジュールがロードされるときに非決定的な結果につながる可能性があるため(この問題を参照)、
play.modules.disabled
を使用してモジュールを無効にすることは強くお勧めしません。実際、play.modules.disabled
は、エンドユーザーがデフォルトで有効になっているモジュールをオーバーライドできるようにするためのものです。
§コンパイル時DI
Module
クラスを定義することで、Google GuiceやSpringなどのランタイムDIフレームワークで使用できるコンポーネントを作成しました。Scalaで人気のある代替手段は、コンパイル時DIです。コンパイル時DIでも使用できるコンポーネントを作成するには、コンポーネントの依存関係を宣言するScalaのtrait
を提供します。実行中の例の場合、次のようになります。
import play.api.inject.ApplicationLifecycle
trait MyComponents {
def applicationLifecycle: ApplicationLifecycle
lazy val component: MyComponent = new MyComponentImpl(applicationLifecycle)
}
§Plugin
クラスとplay.plugins
ファイルを削除する
この時点で、コードの移行が成功しているはずです。そのため、Plugin
クラスとplay.plugins
ファイルの両方を削除する時間です。後者は通常、プロジェクトのconf
フォルダーにあります。
このドキュメントにエラーを見つけましたか?このページのソースコードはこちらにあります。ドキュメントガイドラインを読んだ後、プルリクエストを送信することを遠慮なく行ってください。質問やアドバイスを共有したいですか?コミュニティフォーラムにアクセスして、コミュニティとの会話を開始してください。