Maven의 dependencyManagement와 종속성의 차이점
dependencyManagement
과 의 차이점은 무엇입니까 dependencies
? Apache Maven 웹 사이트에서 문서를 보았습니다. 에서 정의 된 종속성 dependencyManagement
은 버전을 지정하지 않고 자식 모듈에서 사용할 수있는 것 같습니다 .
예를 들면 :
상위 프로젝트 (Pro-par)는 아래에 종속성을 정의합니다 dependencyManagement
.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8</version>
</dependency>
</dependencies>
</dependencyManagement>
그런 다음 Pro-par의 자식에서 junit을 사용할 수 있습니다.
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
그러나 부모 pom에서 junit을 정의 해야하는지 궁금합니다. 필요한 모듈에서 직접 정의하지 않는 이유는 무엇입니까?
종속성 관리를 사용하면 모든 하위 항목이 상속하는 종속성을 추가하지 않고도 종속성 버전 관리를 통합하고 중앙 집중화 할 수 있습니다. 이것은 공통 부모를 상속하는 프로젝트 세트 (즉, 둘 이상)가 있을 때 특히 유용합니다 .
의 또 다른 매우 중요한 사용 사례는 dependencyManagement
전 이적 종속성에 사용되는 아티팩트 버전의 제어입니다. 이것은 예없이 설명하기 어렵습니다. 다행히 문서에 설명되어 있습니다.
나는이 질문에 멋지게 늦었지만 받아 들여진 것보다 더 명확한 대답을 할 가치가 있다고 생각합니다 (정확하지만 당신이 추론해야하는 실제 중요한 부분을 강조하지는 않습니다).
상위 POM에서과의 주요 차이점은 다음 <dependencies>
과 <dependencyManagement>
같습니다.
<dependencies>
섹션에 지정된 아티팩트 는 항상 하위 모듈의 종속성으로 포함됩니다.
<dependencyManagement>
섹션에 지정된 아티팩트 <dependencies>
는 하위 모듈 자체 의 섹션 에도 지정된 경우에만 하위 모듈에 포함됩니다. 물어 보는 것이 좋은 이유는 무엇입니까? 상위에서 버전 및 / 또는 범위를 지정하고 하위 POM에서 종속성을 지정할 때이를 생략 할 수 있기 때문입니다. 이렇게하면 각 하위 모듈에 버전을 지정하지 않고도 하위 모듈의 종속성에 통합 버전을 사용할 수 있습니다.
Maven 사이트 의 문서 는 끔찍합니다. dependencyManagement가하는 일은 단순히 종속성 정의 (버전, 제외 등)를 상위 pom으로 이동 한 다음 하위 poms에 groupId 및 artifactId를 입력하면됩니다. 그게 다입니다 (부모 pom 체인 등을 제외하고는 실제로 복잡하지 않습니다-dependencyManagement는 부모 수준에서 종속성보다 우세합니다-그러나 그것에 대해 질문이 있거나 가져 오기에 대한 질문이 있으면 Maven 문서가 조금 더 좋습니다).
Maven 사이트에서 'a', 'b', 'c'쓰레기를 모두 읽고 혼란스러워서 나는 그들의 예제를 다시 썼습니다. 따라서 공통 종속성 (betaShared)을 공유하는 2 개의 프로젝트 (proj1 및 proj2)가있는 경우 해당 종속성을 상위 pom으로 이동할 수 있습니다. 당신이 그것에있는 동안 당신은 또한 다른 의존성 (alpha 및 charlie)을 위로 이동할 수 있지만 프로젝트에 적합한 경우에만 가능합니다. 따라서 이전 문장에 설명 된 상황의 경우 다음은 상위 pom에 dependencyManagement가있는 솔루션입니다.
<!-- ParentProj pom -->
<project>
<dependencyManagement>
<dependencies>
<dependency> <!-- not much benefit defining alpha here, as we only use in 1 child, so optional -->
<groupId>alpha</groupId>
<artifactId>alpha</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>zebra</groupId>
<artifactId>zebra</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>charlie</groupId> <!-- not much benefit defining charlie here, so optional -->
<artifactId>charlie</artifactId>
<version>1.0</version>
<type>war</type>
<scope>runtime</scope>
</dependency>
<dependency> <!-- defining betaShared here makes a lot of sense -->
<groupId>betaShared</groupId>
<artifactId>betaShared</artifactId>
<version>1.0</version>
<type>bar</type>
<scope>runtime</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
<!-- Child Proj1 pom -->
<project>
<dependencies>
<dependency>
<groupId>alpha</groupId>
<artifactId>alpha</artifactId> <!-- jar type IS DEFAULT, so no need to specify in child projects -->
</dependency>
<dependency>
<groupId>betaShared</groupId>
<artifactId>betaShared</artifactId>
<type>bar</type> <!-- This is not a jar dependency, so we must specify type. -->
</dependency>
</dependencies>
</project>
<!-- Child Proj2 -->
<project>
<dependencies>
<dependency>
<groupId>charlie</groupId>
<artifactId>charlie</artifactId>
<type>war</type> <!-- This is not a jar dependency, so we must specify type. -->
</dependency>
<dependency>
<groupId>betaShared</groupId>
<artifactId>betaShared</artifactId>
<type>bar</type> <!-- This is not a jar dependency, so we must specify type. -->
</dependency>
</dependencies>
</project>
당신이 말한 것과 같습니다. dependencyManagement
모든 종속성 정보를 공통 POM 파일로 가져와 하위 POM 파일의 참조를 단순화하는 데 사용됩니다.
여러 하위 프로젝트에서 다시 입력하고 싶지 않은 여러 속성이있을 때 유용합니다.
Finally, dependencyManagement
can be used to define a standard version of an artifact to use across multiple projects.
There's still one thing that is not highlighted enough, in my opinion, and that is unwanted inheritance.
Here's an incremental example:
I declare in my parent
pom:
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
</dependencies>
boom! I have it in my Child A
, Child B
and Child C
modules:
- Implicilty inherited by child poms
- A single place to manage
- No need to redeclare anything in child poms
- I can still redelcare and override to
version 18.0
in aChild B
if I want to.
But what if I end up not needing guava in Child C
, and neither in the future Child D
and Child E
modules?
They will still inherit it and this is undesired! This is just like Java God Object code smell, where you inherit some useful bits from a class, and a tonn of unwanted stuff as well.
This is where <dependencyManagement>
comes into play. When you add this to your parent pom, all of your child modules STOP seeing it. And thus you are forced to go into each individual module that DOES need it and declare it again (Child A
and Child B
, without the version though).
And, obviously, you don't do it for Child C
, and thus your module remains lean.
There are a few answers outlining differences between <depedencies>
and <dependencyManagement>
tags with maven.
However, few points elaborated below in a concise way:
<dependencyManagement>
allows to consolidate all dependencies (used at child pom level) used across different modules -- clarity, central dependency version management<dependencyManagement>
allows to easily upgrade/downgrade dependencies based on need, in other scenario this needs to be exercised at every child pom level -- consistency- dependencies provided in
<dependencies>
tag is always imported, while dependencies provided at<dependencyManagement>
in parent pom will be imported only if child pom has respective entry in its<dependencies>
tag.
If the dependency was defined in the top-level pom's dependencyManagement element, the child project did not have to explicitly list the version of the dependency. if the child project did define a version, it would override the version listed in the top-level POM’s dependencyManagement section. That is, the dependencyManagement version is only used when the child does not declare a version directly.
Sorry I am very late to the party.
Let me try to explain the difference using mvn dependency:tree
command
Consider the below example
Parent POM - My Project
<modules>
<module>app</module>
<module>data</module>
</modules>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
</dependencies>
</dependencyManagement>
Child POM - data module
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>
Child POM - app module (has no extra dependency, so leaving dependencies empty)
<dependencies>
</dependencies>
On running mvn dependency:tree
command, we get following result
Scanning for projects...
------------------------------------------------------------------------
Reactor Build Order:
MyProject
app
data
------------------------------------------------------------------------
Building MyProject 1.0-SNAPSHOT
------------------------------------------------------------------------
--- maven-dependency-plugin:2.8:tree (default-cli) @ MyProject ---
com.iamvickyav:MyProject:pom:1.0-SNAPSHOT
\- com.google.guava:guava:jar:19.0:compile
------------------------------------------------------------------------
Building app 1.0-SNAPSHOT
------------------------------------------------------------------------
--- maven-dependency-plugin:2.8:tree (default-cli) @ app ---
com.iamvickyav:app:jar:1.0-SNAPSHOT
\- com.google.guava:guava:jar:19.0:compile
------------------------------------------------------------------------
Building data 1.0-SNAPSHOT
------------------------------------------------------------------------
--- maven-dependency-plugin:2.8:tree (default-cli) @ data ---
com.iamvickyav:data:jar:1.0-SNAPSHOT
+- org.apache.commons:commons-lang3:jar:3.9:compile
\- com.google.guava:guava:jar:19.0:compile
Google guava is listed as dependency in every module (including parent), whereas the apache commons is listed as dependency only in data module (not even in parent module)
In the parent POM, the main difference between the <dependencies>
and <dependencyManagement>
is this:
Artifacts specified in the <dependencies>
section will ALWAYS be included as a dependency of the child module(s).
Artifacts specified in the section, will only be included in the child module if they were also specified in the section of the child module itself. Why is it good you ask? because you specify the version and/or scope in the parent, and you can leave them out when specifying the dependencies in the child POM. This can help you use unified versions for dependencies for child modules, without specifying the version in each child module.
In Eclipse, there is one more feature in the dependencyManagement
. When dependencies
is used without it, the unfound dependencies are noticed in the pom file. If dependencyManagement
is used, the unsolved dependencies remain unnoticed in the pom file and errors appear only in the java files. (imports and such...)
The difference between the two is best brought in what seems a necessary and sufficient definition of the dependencyManagement element available in Maven website docs:
dependencyManagement
"Default dependency information for projects that inherit from this one. The dependencies in this section are not immediately resolved. Instead, when a POM derived from this one declares a dependency described by a matching groupId and artifactId, the version and other values from this section are used for that dependency if they were not already specified." [ https://maven.apache.org/ref/3.6.1/maven-model/maven.html ]
It should be read along with some more information available on a different page:
“..the minimal set of information for matching a dependency reference against a dependencyManagement section is actually {groupId, artifactId, type, classifier}. In many cases, these dependencies will refer to jar artifacts with no classifier. This allows us to shorthand the identity set to {groupId, artifactId}, since the default for the type field is jar, and the default classifier is null.” [https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html ]
Thus, all the sub-elements (scope, exclusions etc.,) of a dependency element--other than groupId, artifactId, type, classifier, not just version--are available for lockdown/default at the point (and thus inherited from there onward) you specify the dependency within a dependencyElement. If you’d specified a dependency with the type and classifier sub-elements (see the first-cited webpage to check all sub-elements) as not jar and not null respectively, you’d need {groupId, artifactId, classifier, type} to reference (resolve) that dependency at any point in an inheritance originating from the dependencyManagement element. Else, {groupId, artifactId} would suffice if you do not intend to override the defaults for classifier and type (jar and null respectively). So default is a good keyword in that definition; any sub-element(s) (other than groupId, artifactId, classifier and type, of course) explicitly assigned value(s) at the point you reference a dependency override the defaults in the dependencyManagement element.
So, any dependency element outside of dependencyManagement, whether as a reference to some dependencyManagement element or as a standalone is immediately resolved (i.e. installed to the local repository and available for classpaths).
'Development Tip' 카테고리의 다른 글
차이점 (0) | 2020.09.30 |
---|---|
숫자 배열의 합을 찾는 방법 (0) | 2020.09.30 |
파이썬`x가 None이 아니면`아니면`x가 None`이 아니면? (0) | 2020.09.30 |
소수점 범위 () 단계 값을 사용하는 방법은 무엇입니까? (0) | 2020.09.30 |
git에서 두 커밋 사이에 변경된 줄 수를 어떻게 계산할 수 있습니까? (0) | 2020.09.30 |