事前の最適化
この章では、Spring の事前最適化を基盤とした Spring Data の Ahead of Time (AOT) 最適化について説明します。
事前コード生成
事前コード生成は、GraalVM Native Image での使用に限定されず、通常の デプロイで作業する場合にも利点があり、JVM での起動パフォーマンスの最適化に役立ちます。
AOT 最適化により、一部の決定 (たとえば、データベースダイアレクトなど) はビルド時に固定され、そのままアプリケーションセットアップに組み込まれます。 |
Ahead of Time コンパイルが有効になっている場合、Spring Data は (実際に使用されているモジュールに応じて) ビルドの AOT フェーズ中にいくつかのコンポーネントを提供できます。
生成された型 / プロパティアクセサーのバイトコード
定義されたリポジトリインターフェースのソースコード
JSON 形式のリポジトリメタデータ
上記の各機能はデフォルトで有効になっています。ただし、ユーザーは以下のオプションを使用して設定を微調整できます。
| 生成された型 / プロパティアクセサーのバイトコードのコントリビュートを制御するブールフラグ |
| 生成された型 / プロパティアクセサーのバイトコードを提供する FQCN のカンマ区切りリスト。パッケージ名(例: |
| 生成された型 / プロパティアクセサーのバイトコード提供をスキップする FQCN のカンマ区切りリスト。パッケージ名(例: |
| リポジトリインターフェースのソースコードのコントリビュートを制御するブールフラグ |
| 特定のモジュールのリポジトリインターフェースのソースコードのコントリビュートを制御するブールフラグ (例: |
| クエリメソッドと実際のクエリ文字列を含む JSON リポジトリメタデータの提供を制御するブールフラグ。 |
事前リポジトリ
Ahead of Time リポジトリは、特定のモジュールの命令型(非リアクティブ)リポジトリインターフェースでのみ利用可能です。利用可能なクエリメソッドを特定する条件は、実装モジュールによって異なります。 |
AOT リポジトリは、適切なクエリメソッド実装を事前に生成することで AOT 処理を拡張するものです。クエリメソッドは、その呼び出しで実行されるクエリについて開発者には不透明です。AOT リポジトリは、ビルド時に既知の派生クエリ、アノテーション付きクエリ、名前付きクエリに基づいて、クエリメソッド実装を提供します。この最適化により、クエリメソッド処理が実行時からビルド時へと移行されます。これにより、アプリケーションの起動時にクエリメソッドをリフレクション的に分析する必要がなくなり、パフォーマンスが大幅に向上します。
結果として得られる AOT リポジトリフラグメントは、<Repository FQCN>Impl__AotRepository の命名スキームに従い、リポジトリインターフェースと同じパッケージに配置されます。
AOT リポジトリクラスは内部最適化を目的としています。生成と実装の詳細は将来のリリースで変更される可能性があるため、コード内で直接使用しないでください。 |
リポジトリメタデータ
AOT 処理はクエリメソッドをイントロスペクトし、リポジトリクエリに関するメタデータを収集します。Spring Data は、このメタデータを同じパッケージ内のソースリポジトリにちなんで命名された JSON ファイルに保存します。リポジトリ JSON メタデータには、クエリとフラグメントに関する詳細が含まれます。以下のリポジトリの例を以下に示します。
メタデータ
リポジトリ
{
"name": "example.springdata.UserRepository",
"module": "JDBC",
"type": "IMPERATIVE",
"methods": [
{
"name": "findBy",
"signature": "public abstract java.util.List<example.springdata.User> example.springdata.UserRepository.findBy()",
"query": {
"query": "SELECT * FROM User"
}
},
{
"name": "findByLastnameStartingWith",
"signature": "public abstract org.springframework.data.domain.Page<example.springdata.User> example.springdata.UserRepository.findByLastnameStartingWith(java.lang.String,org.springframework.data.domain.Pageable)",
"query": {
"query": "SELECT * FROM User u WHERE lastname LIKE :lastname",
"count-query": "SELECT COUNT(*) FROM User WHERE lastname LIKE :lastname"
}
},
{
"name": "findByEmailAddress",
"signature": "public abstract example.springdata.User example.springdata.UserRepository.findByEmailAddress(java.lang.String)",
"query": {
"query": "select * from User where emailAddress = ?1"
}
},
interface UserRepository extends CrudRepository<User, Integer> {
List<User> findBy();
Page<User> findByLastnameStartingWith(String lastname, Pageable page);
@Query("select * from User where emailAddress = ?1")
User findByEmailAddress(String username);
}
JSON メタデータの作成は、 |
ネイティブイメージランタイムのヒント
アプリケーションをネイティブイメージとして実行するには、通常の JVM ランタイムに比べて追加の情報が必要です。Spring Data は、ネイティブイメージの使用に関する AOT 処理中に実行時のヒントを提供します。これらは特に、以下の点に関するヒントです。
監査
クラスパススキャンの結果をキャプチャーするための
ManagedTypesリポジトリ
エンティティ、戻り値の型、Spring Data アノテーションのリフレクションヒント
リポジトリフラグメント
Querydsl
QクラスKotlin コルーチンサポート
Web サポート (Jackson の
PagedModelのヒント)