Java読書会「The Java Module System」を読む会(第1~3回)のまとめ(その2)
の続きです。
第2章 Anatomy of a modular application
モジュール化したアプリケーションのディレクトリ構成の例
+- libs (サードパーティの依存物) +- mods (コンパイル&パッケージ化したモジュール) +- monitor (アプリケーションモジュールの1つ) | +- src | | +- main | | +- java (モジュールのソースコードを含む) | | +- monitor | | +- module-info.java (モジュールの宣言) | +- target | +- classes (モジュールのコンパイル結果を格納) +- monitor.observer (モジュール) | +- src
- 慣例で、modsフォルダーに生成したモジュールを格納
モジュール化するアプリケーションの作成の流れ
- アプリケーションをモジュールに分解する(関心事の分離戦略がよい)
- ディレクトリ構造の作成
- モジュール宣言
- 別モジュールへの依存関係の宣言
- モジュール公開APIの定義
- モジュールグラフの可視化
- コンパイルとパッケージ化
他のモジュールに依存のないモジュールのビルド
$ java -d monitor.observer/target/classes ${source-files} $ jar --create --file mods/monitor.observer.jar -C monitor.observer/target/classes .
他のモジュールに依存のあるモジュールのビルド
$ java --module-path mods -d monitor.observer.alpha/target/classes ${source-files} $ jar --create --file mods/monitor.observer.alpha.jar -C monitor.observer.alpha/target/classes .
依存するモジュールのあるフォルダを --module-pathオプションで指定します。
2つのフォルダにあるモジュールに依存のあるモジュールのビルド
アプリケーションのモジュールとサードパーティのモジュールとに依存のあるモジュールをビルドします。 --module-pathオプションで複数のフォルダを指定可能です。
$ javac --module-path mods:libs -d monitor.rest/target/classes ${source-files} $ jar --create --file mods/monitor.rest.jar -C monitor.rest/target/classes .
メインメソッドを持つクラスを含むモジュールのビルド
$ javac --module-path mods -d monitor/target/classes ${source-files} $ jar --create --file mods/monitor.jar --main-class monitor.Monitor -C monitor/target/classes .
アプリケーションの実行
$ java --module-path mods:libs --module monitor
モジュールパスでモジュールを収容するフォルダを指定、メインを持つモジュールの名前を指定して実行します。
第3章 Defining modules and their properties
2つのモジュールファイルフォーマット
- JMOD
JDKを構成するモジュールはJMODフォーマットで提供されています。アプリケーション開発者にはJMODファイルを生成する機能は提供されていません - モジュラーJAR 通常のJARファイル内のルートディレクトリにモジュール記述子module-info.classが含まれているものです。
モジュラーJARをクラスパスに置くと、モジュール定義が無視され従来のJARファイルとして扱われます。
モジュール宣言(module-info.java)
module モジュール名 { requires モジュール名; exports パッケージ名; }
モジュール名とパッケージ名の両方が登場し、命名規則が類似しているので混乱しがちです。
ルートモジュールからの依存性解析結果に含まれないモジュールは使用できません。 そこで、javaコマンドのオプション --add-modules や --add-reads で補うことができます。
- --add-modulesは、指定したモジュール群を、ルートモジュールとして扱う
- --add-readsは、指定したモジュールから、指定したターゲットモジュール群へrequiresなしでもアクセス可能とする
モジュール宣言(module-info.java)をコンパイルして生成されるクラスmodule-info.classは、モジュール記述子と呼びます。
モジュール名を付けるには次が重要です。
- グローバルユニーク
- 安定
ベストな命名は、ドメイン名の逆順です。これはパッケージ名の命名と同じルールです。そのため、モジュールに含まれるパッケージのパッケージ名のプレフィックスをモジュール名にするとよいです。
モジュールの種類
- アプリケーションモジュール
JDK以外のモジュール。モジュールパス上に置き、モジュラーJAR形式 - イニシャルモジュール
コンパイル開始対象モジュール、またはmainメソッドを持つモジュール - ルートモジュール
JPMSが依存関係解決にとりかかる対象モジュールで、イニシャルモジュールはルートモジュールでもある - プラットフォームモジュール
JDKを構成するモジュール。JMODファイルで提供 - インキュベーターモジュール
非標準なプラットフォームモジュール。jdk.incubator.* - システムモジュール
プラットフォームモジュールのサブセットで実行イメージ用に抜粋したものと、jlinkが追加したアプリケーションモジュールから構成。
java --list-modules で一覧されるもの。 - オブザーバブルモジュール
現在のランタイムにあるすべてのプラットフォームモジュールと、コマンドラインで指定したアプリケーションモジュール - ベースモジュール
java.base - 明示的なモジュール
プラットフォームモジュールと、モジュール記述子(module-info.class)を持つアプリケーションモジュール - 自動モジュール
モジュール記述子を持たない、名前が指定されたモジュール(モジュールパスに置いたプレーンJAR) - 名前付きモジュール
明示的なモジュールと自動モジュールの総称。モジュール記述子で定義した名前またはJPMSが推論した名前 - 名前なしモジュール
クラスパス上にあるコンテンツ
このうち、自動モジュールと名前なしモジュールはマイグレーションの過程で使用します。
requiresするのは直接利用しているモジュールのみでよい
monitor.persistence ↓ monitor.statistics ↓ monitor.observer
このモジュール依存関係の場合、monitor.persistenceはmonitor.statisticsをrequiresすればよく、monitor.observerのrequiresは不要です。 また、monitor.persistenceをコンパイルする場合、monitor.statisticsモジュールが存在すればよく、monitor.observerモジュールは存在しなくても構いません。ただし、実行時にはすべてのモジュールが必要です。