倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

POM ファイルを書こう! 其ノ参 - 依存性の推移

依存性の推移


今回は 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のようになります:
f:id:waman:20070809034301p:image

「実行時」に必要とされるライブラリは説明の必要はないかと思います。

一方、「コンパイル時」に必要となるライブラリに対しては、ライブラリとは基本的にクラスファイル(バイトコード)だってことから、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のようになって、依存関係の推移性の表と一致しません。 うーむ。

f:id:waman:20070809033835p:image

この辺りの違いから、スコープのテクニカルな使い方が編み出せそうな気もしますが・・・

*1:依存関係を付加したライブラリが依存しているライブラリ

*2:いまいちいってる状況が分かりません。 拙者の英語力の問題ではないと思うんですが・・・。 ちなみにこれは compile → compile が compile になる説明に対する注意書きなので、ここに書くのは間違ってるかも。