依存性の推移
今回は Maven2 の POM ファイルで指定した依存性の推移を考えましょう( 一覧)。 公式には こちらを参照のこと。
依存性の推移とは、間接的に依存関係があるライブラリ*1に対して、どのような依存関係でそれを取り込むかってことです。 取り込むというのは、依存関係のスコープをどのようにするかという意味です。
ちなみに、前回説明しましたが、スコープとは「ライブラリをいつクラスパスに含めるか?」ってことでした。
推移のルール
基本的に下記の表を理解しておけば、依存性の推移はバッチリです。
compile | provided | runtime | test | |
---|---|---|---|---|
compile | compile | - | runtime | - |
provided | provided | provided | provided | - |
runtime | runtime | - | runtime | - |
test | test | - | test | - |
表の見方は
- 左端のスコープは、自分のプロジェクト内でライブラリに対して指定したもの。
- 上端のスコープは、そのライブラリがさらに依存しているライブラリに対して指定しているもの。
- その行と列が交わるところが、間接的に依存しているライブラリが指定されていると見なされるスコープです。
例えば、commons-logging-1.1 では log4j-1.2.12 が compile スコープで指定されています。 したがって、自分のプロジェクトで commons-logging-1.1 を compile スコープで指定した場合、そのプロジェクトでは log4j-1.2.12 が compile スコープで指定されていると見なされます。
ルールをちょっと考察
スコープの推移性は上記のルール(表)で全てが終わってますが、ちょっと表の中身を考察してみましょう。
依存性のスコープとは、「ライブラリをいつクラスパスに含めるか?」ってことでした。 クラスパスが参照されるのは「コンパイル時」と「実行時」で、スコープは
- コンパイル時 → provided
- 実行時 → runtime
と対応します。 compile スコープは「コンパイル時」と「実行時」に参照されるので、
compile = provided + runtime
と思って、スコープの推移性がどうなるか考えてみましょう(実はちょっとうまくいきません・・・)。
provided と runtime しか指定されていない場合
「コンパイル時」と「実行時」に必要なライブラリを全て別々に指定した場合、2次的なライブラリに対するスコープは図1のようになります:
「実行時」に必要とされるライブラリは説明の必要はないかと思います。
一方、「コンパイル時」に必要となるライブラリに対しては、ライブラリとは基本的にクラスファイル(バイトコード)だってことから、provided → runtime (Library B) は必要でも、provided → provided (Library A) は不必要な気がします。 が、Maven2 のサイトによると
there is the case where the library you depend on extends a class from another library, forcing you to have available at compile time.
だそうなので*2、provided スコープのライブラリが依存しているライブラリは、コンパイル時にクラスパスに含められます。
compile スコープがある場合
compile スコープを provided + runtime と見なすと、図1で provided と runtime が同じライブラリを指していると見なせます。
- まず、依存先のライブラリに compile スコープがある場合は、図2のようになります(図1の Library A と Library B が同一のライブラリ Library AB を指していると見ます)。 これは依存関係の推移性の表と一致します。
- また、自分のプロジェクトが直接 compile スコープを指定しているライブラリが、さらに compile スコープを指定している場合、(図は載せてませんが)そのライブラリも compile スコープと見なされることになり、依存関係の推移性の表と一致します。
- 一方、自分のプロジェクトが compile スコープを指定しているライブラリが provided, runtime を指定している場合、上と同様のことをすると図3のようになって、依存関係の推移性の表と一致しません。 うーむ。
この辺りの違いから、スコープのテクニカルな使い方が編み出せそうな気もしますが・・・