§コンパイル時依存性注入
Playは、すぐに使用できるランタイム依存性注入のメカニズムを提供します。つまり、依存関係が実行時まで接続されない依存性注入です。このアプローチには、利点と欠点の両方があります。主な利点は、ボイラープレートコードの最小化であり、主な欠点は、アプリケーションの構築がコンパイル時に検証されないことです。
代替アプローチとして、コンパイル時依存性注入を使用できます。最も単純なコンパイル時DIは、依存関係を手動で構築および接続することで実現できます。Daggerなどの他のより高度なテクニックとツールが存在します。これらはすべて、コンストラクタと手動配線の上に簡単に実装できるため、Playのコンパイル時依存性注入のサポートは、パブリックコンストラクタとファクトリメソッドをAPIとして提供することで実現されます。
注記:コンパイル時DIまたはDI全般について初めての場合は、Adam WarskiのScalaのDIに関するガイドを読む価値があります。これはScala開発者向けの解説ですが、コンパイル時注入の利点についても理解を深めることができます。
パブリックコンストラクタとファクトリメソッドを提供することに加えて、Playのすぐに使用できるすべてのモジュールは、便宜上、軽量なケーキパターンを実装するインターフェースを提供します。これらはパブリックコンストラクタの上に構築されており、完全にオプションです。一部のアプリケーションでは、これらを使用することは適切ではありませんが、多くのアプリケーションでは、Playによって提供されるコンポーネントを接続する非常に便利なメカニズムになります。これらのインターフェースは、トレイト名の末尾にComponentsという命名規則に従います。たとえば、DB APIのデフォルトのHikariCPベースの実装は、HikariCPComponentsというインターフェースを提供します。
注記:もちろん、Javaにはケーキパターンを完全に実装するためのいくつかの制限があります。たとえば、インターフェースに状態を持たせることはできません。
以下の例では、組み込みのコンポーネントヘルパーインターフェースを使用して、Playアプリケーションを手動で接続する方法を示します。提供されているコンポーネントインターフェースのソースコードを読むことで、これを他の依存性注入テクニックにも簡単に適用できます。
§アプリケーションのエントリポイント
JVMで実行されるアプリケーションには、リフレクションによってロードされるエントリポイントが必要です。アプリケーション自体が起動する場合でも、メインクラスは依然としてリフレクションによってロードされ、そのメインメソッドはリフレクションを使用して配置および呼び出されます。
Playの開発モードでは、Playで使用されるJVMとHTTPサーバーは、アプリケーションの再起動の間、実行状態を維持する必要があります。これを実装するために、Playは実装できるApplicationLoaderインターフェースを提供します。アプリケーションローダーは、アプリケーションがリロードされるたびに構築および呼び出され、アプリケーションをロードします。
このインターフェースのloadメソッドは、アプリケーションローダーContextを引数として受け取ります。これには、アプリケーション自体よりも長持ちし、アプリケーション自体では構築できないPlayアプリケーションに必要なすべてのコンポーネントが含まれています。これらのコンポーネントの中には、開発モードで機能を提供する目的で存在するものもあり、たとえば、ソースマッパーにより、Playエラーハンドラーは例外がスローされた場所のソースコードをレンダリングできます。
これの最も単純な実装は、PlayのBuiltInComponentsFromContext抽象クラスを拡張することで提供できます。このクラスはコンテキストを受け取り、そのコンテキストに基づいてすべての組み込みコンポーネントを提供します。提供する必要があるのは、Playがリクエストをルーティングするためのルーターだけです。以下は、この方法で空のルーターを使用して作成できる最も単純なアプリケーションです。
import play.Application;
import play.ApplicationLoader;
import play.BuiltInComponentsFromContext;
import play.LoggerConfigurator;
import play.controllers.AssetsComponents;
import play.db.ConnectionPool;
import play.db.HikariCPComponents;
import play.filters.components.HttpFiltersComponents;
import play.mvc.Results;
import play.routing.Router;
import play.routing.RoutingDslComponentsFromContext;
public class MyComponents extends BuiltInComponentsFromContext implements HttpFiltersComponents {
public MyComponents(ApplicationLoader.Context context) {
super(context);
}
@Override
public Router router() {
return Router.empty();
}
}
そして、アプリケーションローダー
public class MyApplicationLoader implements ApplicationLoader {
@Override
public Application load(Context context) {
return new MyComponents(context).application();
}
}
このアプリケーションローダーを使用するようにPlayを設定するには、application.confファイルで、play.application.loaderプロパティを完全修飾クラス名に設定します。
play.application.loader=MyApplicationLoader
さらに、組み込みのGuiceモジュールを使用する既存のプロジェクトを変更する場合は、`build.sbt`の`libraryDependencies`から`guice`を削除できるはずです。
§ルーターの提供
ルーターを設定するには、RoutingDslまたは生成されたルーターの2つのオプションがあります。
§RoutingDslを使ったルーターの提供
これを容易にするために、Playには、他の提供されたコンポーネントを使用して作成されたRoutingDslインスタンスを既に提供するRoutingDslComponentsFromContextクラスがあります。
public class MyComponentsWithRouter extends RoutingDslComponentsFromContext
implements HttpFiltersComponents {
public MyComponentsWithRouter(ApplicationLoader.Context context) {
super(context);
}
@Override
public Router router() {
// routingDsl method is provided by RoutingDslComponentsFromContext
return routingDsl().GET("/path").routingTo(request -> Results.ok("The content")).build();
}
}§生成されたルーターの使用
デフォルトでは、Playは注入されたルートジェネレーターを使用します。これは、ルートファイルにある各コントローラーと含まれるルーターを、ルートファイルに表示される順序で受け入れるコンストラクタを持つルーターを生成します。ルーターのコンストラクタは、最初の引数として、パラメーターバインディングエラーを処理するために使用されるplay.api.http.HttpErrorHandler(play.http.HttpErrorHandlerのScalaバージョン)と、最後の引数としてプレフィックス文字列を受け入れます。これを"/"にデフォルト設定するオーバーロードされたコンストラクタも提供されます。
次のルート
GET / controllers.HomeController.index
GET /assets/*file controllers.Assets.at(path = "/public", file)
は、`controllers.HomeController`、`controllers.Assets`、およびルートが宣言されている他のインスタンスを受け入れるルーターを生成します。これを実際のアプリケーションで使用するには
public class MyComponentsWithGeneratedRouter extends BuiltInComponentsFromContext
implements HttpFiltersComponents, AssetsComponents {
public MyComponentsWithGeneratedRouter(ApplicationLoader.Context context) {
super(context);
}
@Override
public Router router() {
HomeController homeController = new HomeController();
Assets assets =
new Assets(scalaHttpErrorHandler(), assetsMetadata(), environment().asScala());
return new router.Routes(scalaHttpErrorHandler(), homeController,
return new javaguide.dependencyinjection.Routes(
scalaHttpErrorHandler(), homeController, assets)
.asJava();
}
}§ロギングの設定
Playでロギングを正しく設定するには、アプリケーションが返される前にLoggerConfiguratorを実行する必要があります。デフォルトのBuiltInComponentsFromContextは、LoggerConfiguratorを呼び出しません。
この初期化コードは、アプリケーションローダーに追加する必要があります。
import scala.jdk.javaapi.OptionConverters;
public class MyAppLoaderWithLoggerConfiguration implements ApplicationLoader {
@Override
public Application load(Context context) {
LoggerConfigurator.apply(context.environment().classLoader())
.ifPresent(
loggerConfigurator ->
loggerConfigurator.configure(context.environment(), context.initialConfig()));
return new MyComponents(context).application();
}
}§他のコンポーネントの使用
前述のように、Playは他のコンポーネントを接続するための多くのヘルパートレイトを提供します。たとえば、データベース接続プールを使用する場合は、次のようにHikariCPComponentsをコンポーネントケーキにミックスインできます。
public class MyComponentsWithDatabase extends BuiltInComponentsFromContext
implements HikariCPComponents, HttpFiltersComponents {
public MyComponentsWithDatabase(ApplicationLoader.Context context) {
super(context);
}
@Override
public Router router() {
return Router.empty();
}
public SomeComponent someComponent() {
// connectionPool method is provided by HikariCPComponents
return new SomeComponent(connectionPool());
}
}
CSRFComponentsやAhcWSComponentsなど、他のヘルパートレイトも利用できます。コンポーネントを提供するJavaインターフェースの完全なリストは次のとおりです。
play.BuiltInComponentsplay.components.PekkoComponentsplay.components.ApplicationComponentsplay.components.BaseComponentsplay.components.BodyParserComponentsplay.components.ConfigurationComponentsplay.components.CryptoComponentsplay.components.FileMimeTypesComponentsplay.components.HttpComponentsplay.components.HttpConfigurationComponentsplay.components.HttpErrorHandlerComponentsplay.components.TemporaryFileComponentsplay.controllers.AssetsComponentsplay.i18n.I18nComponentsplay.libs.ws.ahc.AhcWSComponentsplay.libs.ws.ahc.WSClientComponentsplay.cache.ehcache.EhCacheComponentsplay.filters.components.AllowedHostsComponentsplay.filters.components.CORSComponentsplay.filters.components.CSRFComponentsplay.filters.components.GzipFilterComponentsplay.filters.components.HttpFiltersComponentsplay.filters.components.NoHttpFiltersComponentsplay.filters.components.RedirectHttpsComponentsplay.filters.components.SecurityHeadersComponentsplay.routing.RoutingDslComponentsplay.data.FormFactoryComponentsplay.data.validation.ValidatorsComponentsplay.db.ConnectionPoolComponentsplay.db.DBComponentsplay.db.HikariCPComponentsplay.db.jpa.JPAComponentsplay.libs.openid.OpenIdComponents
次へ: アプリケーション設定
このドキュメントにエラーが見つかりましたか?このページのソースコードはこちらにあります。ドキュメントガイドラインを読んだ後、プルリクエストを自由に投稿してください。ご質問やアドバイスがありましたら、コミュニティフォーラムにアクセスして、コミュニティと会話を始めましょう。