TL; DR A)いいえ; B)いいえ; もしあなた<resources>
がそうなら、あなたは<resources combine.children="append">
それを省略することができますが、書かれているように、いいえ
長い答え
ルートからビルドを実行し、BがAに依存していると仮定した場合
取得するクラスパスは、reactor全体を進めるフェーズによって異なります。
フェーズがライフサイクルのフェーズの前にある場合package
、クラスパスは${project.build.outputDirectory}
reactor内の依存関係のディレクトリを参照します
フェーズがライフサイクルのフェーズ上またはpackage
フェーズの後にある場合、クラスパスは構築されたJARファイルを参照します。${project.build.directory}/${project.build.finalName}.jar
だからあなたにいくつかの具体的な例を与えるために:
$ mvn compile
<packaging>pom</packaging>
Pはaであり、デフォルトでは、パッケージは[クラスパス関連]プラグインを。より前のライフサイクルフェーズにバインドしないため、これはPでは何もしませんinstall
。
Aを押すと、コンパイルクラスパスにAのすべての依存関係が一覧表示されます。これらはいずれもreactorからのものではないため、ローカルキャッシュ(つまり~/.m2/repository
)から解決されます。したがって、Aがlog4jを使用する場合、次のようなコンパイルクラスパスが作成されます。
${JAVA_HOME}/lib/rt.jar:~/.m2/repository/log4j/log4j/1.2.16/log4j-1.2.16.jar
コンパイル後のフェーズを指定していないため、テストクラスパスを必要とするプラグインは呼び出されないため、現時点では関係ありません。
ここでBに移動します。Bの依存関係にはAが含まれているため、Aのメインアーティファクトを参照します(jar:jar
実行されていないため、Aを指し${project.build.outputDirectory}
ます)。Bのコンパイルクラスパスは次のようになります。
${JAVA_HOME}/lib/rt.jar:~/.m2/repository/log4j/log4j/1.2.16/log4j-1.2.16.jar
:./A/target/classes
[注:Pディレクトリから呼び出したとき、現在のディレクトリはPで${basedir}
あるため、Bの値は]に${basedir}
なります。./B
B自身の依存関係は、pom内の依存関係の順序、および推移的な依存関係に除外またはバージョンオーバーライドを適用するかどうかに応じて、クラスパスを変更する場合があります。
わかった。それは私たちが始めるのに十分簡単でした...次に私たちはライフサイクルをtest
フェーズに移します
$ mvn test
Pは以前と同じ話をしています
Aのコンパイルストーリーは以前と同じです。フェーズにtest-compile
入ると、テストは次のクラスパスでコンパイルされます(テストにjunitを使用すると仮定)
${JAVA_HOME}/lib/rt.jar:~/.m2/repository/log4j/log4j/1.2.16/log4j-1.2.16.jar
:./A/target/classes:~/.m2/repository/junit/junit/4.10/junit-4.10.jar
[確認するためにmvn-Xを掘り下げる必要があるため、要素の順序が少し間違っている可能性がありますが、プリンシパルは正しいです]
test
フェーズに入るとsurefire:test
、テストクラスパスを構築します。デフォルトでは、テストの依存関係を非テストの依存関係よりも優先しますが、構成可能です。したがって、Aのテストクラスは次のようなクラスパスで実行されます
${JAVA_HOME}/lib/rt.jar:./A/target/test-classes:~/.m2/repository/junit/junit/4.10/junit-4.10.jar
:~/.m2/repository/log4j/log4j/1.2.16/log4j-1.2.16.jar:./A/target/classes
これにより、テストクラスパスで一致するリソースを使用して本番環境のデフォルトをオーバーライドし、コードをテスト可能にするなどのことが可能になります。
Bのコンパイルクラスパスは以前と同じです。また、Bが別のバージョンのJUnitに依存していることも示しています。test-compile
クラスパスは驚くべきことではありません
${JAVA_HOME}/lib/rt.jar:~/.m2/repository/log4j/log4j/1.2.16/log4j-1.2.16.jar
:./A/target/classes:./B/target/classes
:~/.m2/repository/junit/junit/4.11/junit-4.11.jar
これで興味深いことになります。surefireによって構築されたBのクラスパス(ここでも、テストスコープの依存関係の順序を変更できるため、デフォルトを使用していると仮定します)。Aのテストクラスパスは推移的ではないため、Bに公開されません。
${JAVA_HOME}/lib/rt.jar:./B/target/test-classes
:~/.m2/repository/junit/junit/4.11/junit-4.11.jar
:~/.m2/repository/log4j/log4j/1.2.16/log4j-1.2.16.jar
:./A/target/classes:./B/target/classes
package
最後に、フェーズまで進んで、それがクラスパスにどのように影響するかを見てみましょう。
$ mvn package
Pは以前と同じです。
Aは、依存関係がリアクター内から発生しないため、実際には以前と同じです。ただし、ここで重要なのはjar:jar
、フェーズで実行するとpackage
、公開されたクラスパスが置き換えられることです...これは、BがAをどのように見るかに影響します。
Bのクラスパスは以前と同じように構築されますが、BはA.jar
のコンパイル済みクラスではなくAを参照するようになりました。したがって、Bのcompile
クラスパスは
${JAVA_HOME}/lib/rt.jar:~/.m2/repository/log4j/log4j/1.2.16/log4j-1.2.16.jar
:./A/target/A-1.0-SNAPSHOT.jar
Bのtest-compile
クラスパスは次のようになります
${JAVA_HOME}/lib/rt.jar:~/.m2/repository/log4j/log4j/1.2.16/log4j-1.2.16.jar
:./A/target/A-1.0-SNAPSHOT.jar:./B/target/classes
:~/.m2/repository/junit/junit/4.11/junit-4.11.jar
Bのtest
クラスパスは次のようになります。
${JAVA_HOME}/lib/rt.jar:./B/target/test-classes
:~/.m2/repository/junit/junit/4.11/junit-4.11.jar
:~/.m2/repository/log4j/log4j/1.2.16/log4j-1.2.16.jar
:./A/target/A-1.0-SNAPSHOT.jar:./B/target/classes
さて、あなたに最終的な絵を与えるためだけに
$ mvn install -DskipTests
$ mvn test -f B/pom.xmml
単一のモジュールリアクターで実行しているMavenの2番目の呼び出し(つまり、Bがリアクター内の唯一のモジュール)では、Aがローカルキャッシュから解決されるため、次のようなテストクラスパスを取得します。
${JAVA_HOME}/lib/rt.jar:./B/target/test-classes
:~/.m2/repository/junit/junit/4.11/junit-4.11.jar
:~/.m2/repository/log4j/log4j/1.2.16/log4j-1.2.16.jar
:~/.m2/repository/com/mydomain/myproject/A/1.0-SNAPSHOT/A-1.0-SNAPSHOT.jar
:./B/target/classes
これで、Mavenのクラスパスの謎がある程度明らかになったと思います。
プロファイルはこれにどのように組み込まれますか...まあ、クラスパスには何もしません。代わりに、ファイルをにコピーします${project.build.outputDirectory
。
Aがprocess-resources
フェーズに達すると、定義されたすべてがコピーさresources
れ${project.build.outputDirectoy}
ます。
$ mvn package -PtheProfile
まったく同じクラスパスを作成しますが、のファイルは、ディレクトリ構造を保持したまま./A/src/main/ctx/someDir
Aにフィルタリングしてコピーされ、のファイルは、ディレクトリ構造を保持したまま、フィルタリングせずにAにコピーされます。次に、フェーズに到達すると、それらのすべてのファイルが再び丸呑みになります。${project.build.outputDirectoy}
./A/src/main/resources
${project.build.outputDirectoy}
package
jar:jar
.jar
この回答が、何がうまくいっているのかを理解するのに役立つことを願っています...また、プロファイルを使用して構築されたアーティファクトに影響を与えることが頭痛の種になる理由を理解し始めていることを願っています。
$ mvn clean install -PtheProfile -DskipTests
$ mvn test -f B/pom.xml
とは異なる結果になります
$ mvn clean install -DskipTests
$ mvn test -f B/pom.xml
ローカルリポジトリキャッシュは、アーティファクトがローカルリポジトリにインストールされたときにアクティブだったプロファイルを認識しないため、最初のケースは2番目のケースとは異なるA.jarを構築します...
しかし、それはあなたが遭遇する可能性のある将来の問題と、推移的に公開されるクラスパスまたは構築されたアーティファクトのいずれかを変更するためにプロファイルの使用を避けることをMavenの方法に固執することを提唱する理由のヒントです。ただし、プロファイルを使用してtest
クラスパスを変更することは非常に便利です(たとえば、テストがJDK1.5、JDK1.6、JDK1.7で実行される場合、テストのクラスパスを変更する必要がある場合があります...これはテストとしては問題ありません。クラスパスは非遷移的です)