1

このように構成されたMavenマルチモジュールプロジェクトでは、次のようになります。

P // parent project
  * A // first module
  * B // second module, containing the test in question

Aのにはこれpom.xmlが含まれています:

 <profile>
   <id>theProfile</id>
     <build>
       <resources>
         <resource>
           <directory>src/main/ctx/someDir</directory>
             <filtering>true</filtering>
         </resource>
         <resource>
         <resource>
           <directory>src/main/resources</directory>
         </resource>
       </resources>
     <build>
   </profile>         

プロジェクトP全体が実行され、このプロファイルがアクティブ化されると、Bsrc/test/resourcesのテスト中のクラスパスの一部としての可用性に何らかの影響がありますか?

はいの場合、どのように、そしてどのように定義を変更して、与えられたリソースが

a)純粋に追加

b)それらが定義されているAにのみ影響します。

いいえの場合、そのsrc/main/resources部分は不要ですか?

4

2 に答える 2

2

簡単な答え:いいえ、いいえ。

A/target/classesプロジェクトAのリソースは、プロセスリソースフェーズ中ににコピーされます。プロファイルが実行しているのは、より多くのリソースをにコピ​​ーすることだけですtarget/classes。つまり、からファイルをコピー(およびフィルタリング)しますsrc/main/ctx/someDir

Bのテストクラスパスは同じままです。BがAに依存していると仮定すると、そのテストクラスパスにはA.jarが含まれ、A.jarにはA/ターゲット/クラスのコンテンツが含まれます。これは、を使用して確認できますmvn dependency:build-classpath。ただし、クラスパスは同じですが、Aのクラスパスエントリの内容は異なります。

なぜあなたが言及src/test/resourceするのかわかりません(私はあなたがタイプミスしたと思いますsrc/test/resources)。テストリソースは、<testResources>要素を使用して個別に管理されます。あなたが意味するならA/src/test/resources、いいえ、それらはBのテストクラスパスに表示されません。を意味する場合はB/src/test/resources、はい、それらはBのテストクラスパスに表示されます。したがって、プロファイルをアクティブ化しても影響はありません。

指定src/main/resourcesは不要ではありません。要素を含める場合は<resources>、プロジェクト内のリソースを含むすべてのディレクトリを含める必要があります。

于 2012-10-18T11:21:54.713 に答える
2

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/someDirAにフィルタリングしてコピーされ、のファイルは、ディレクトリ構造を保持したまま、フィルタリングせずにAにコピーされます。次に、フェーズに到達すると、それらのすべてのファイルが再び丸呑みになります。${project.build.outputDirectoy}./A/src/main/resources${project.build.outputDirectoy}packagejar: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で実行される場合、テストのクラスパスを変更する必要がある場合があります...これはテストとしては問題ありません。クラスパスは非遷移的です)

于 2012-10-18T11:22:45.573 に答える