Maven의 종속성 관리와 종속성의 차이점


766

차이점은 무엇이며 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을 정의해야하는지 궁금합니다. 필요한 모듈에서 직접 정의하지 않겠습니까?

답변:


463

종속성 관리를 통해 모든 자식이 상속하는 종속성을 추가하지 않고도 종속성 버전 관리를 통합하고 중앙 집중화 할 수 있습니다. 이것은 공통 상위를 상속하는 프로젝트 세트 (즉, 둘 이상)가 있을 때 특히 유용합니다 .

또 다른 매우 중요한 유스 케이스는 dependencyManagement전이 종속성에 사용되는 아티팩트 버전을 제어하는 ​​것입니다. 이것은 예없이 설명하기 어렵습니다. 운 좋게도 이것은 문서에 설명되어 있습니다.


17
그래서 <dependencyManagement> 섹션에서 부모 프로젝트의 폼폼에서 선언하더라도 자식 프로젝트 폼의 종속성을 선언해야합니까? 어떤 종류의 의존성을 상속하는 것이 가능합니까?
johnny-b-goode

55
예, 여전히 자식 POM에서이를 사용하고 있음을 나타내도록 정의해야합니다. <dependencyManagement>부모 POM에 포함되어 있기 때문에 실제로 자식 프로젝트에 포함되지 않습니다 . 종속성을 묶으 <dependencyManagement>면 사용하기로 결정한 경우 언제, 각 종속성에 대한 버전, 범위 및 제외를 중앙 집중식으로 관리 할 수 ​​있습니다. 의존성 관리에 대한 Maven의 가이드 는 모든 세부 사항을 다룹니다.
hotshot309

2
두 번째 단락 ( dependencyManagement의존성이 명시 적으로 설정하는 경우도 이적 의존성을 제어)에만 해당됩니다 stackoverflow.com/questions/28312975/...
로버트 메츠거

2
@ johnny-b-goode 여전히 할 수 dependencies있는 것은 부모 pom에 새 섹션을 만드는 것입니다 . 우리는 모든 자식 프로젝트가 기본적으로 아파치 커먼을 갖도록하고 항상 선언하지 않도록했습니다.
рüффп

770

나는이 질문에 유행이 늦었지만 받아 들여진 것보다 명확한 응답의 가치가 있다고 생각합니다 (정확하지만 실제 중요한 부분을 강조하지는 않지만 스스로를 추론해야합니다).

부모 POM에서와의 주요 차이점은 다음 <dependencies><dependencyManagement>같습니다.

<dependencies>섹션에 지정된 아티팩트 는 항상 하위 모듈의 종속성으로 포함됩니다.

<dependencyManagement>섹션에 지정된 아티팩트 <dependencies>는 하위 모듈 자체 의 섹션 에도 지정된 경우에만 하위 모듈에 포함됩니다. 물어 보는 것이 왜 좋은가요? 상위에서 버전 및 / 또는 범위를 지정하고 하위 POM에서 종속성을 지정할 때이를 제외 할 수 있습니다. 이를 통해 각 하위 모듈에 버전을 지정하지 않고도 하위 모듈의 종속성에 통합 버전을 사용할 수 있습니다.


1
그러나 사용, 또한 약간의 오버 헤드 아닌 <dependencyManagement>이상 <dependencies>루트에 .pom? 자녀 pom는 훨씬 짧을 수 있습니다.
Janez Kuhar

18
사실입니다. <dependencyManagement> 대신 <dependencies>를 사용하면 자식 폼이 짧아집니다. 그러나 비용이 함께 제공되므로 모든 하위 모듈에 대해 이러한 종속성이 항상 정의됩니다. 하위 모듈 중 일부만 특정 종속성이 필요한 경우 "<dependencyManagement>"를 사용하는 대신 해당 하위 모듈을 선택하여 상위 pom에서만 종속성 버전을 설정하여 조금 효율적으로 선택할 수 있습니다.
dcoder

2
@JanezKuhar 자식 모듈에서 종속성을 지정하면 부모 모듈의 종속성을 재정의하지만 기억하지 않는다는 것을 인정합니다. 기회가되면 maven 문서를 확인해야합니다. 간단한 부모-자식 프로젝트를 설정하고 확인하는 것이 더 쉬울 수도 있지만 :)
dcoder

26
간단한 개념에 대한 좋은 설명-Maven이 자신의 도구를 쉽게 설명하는 것이 왜 그렇게 어려운 것입니까?
jimmy_terra

1
나는에 추가 할 것입니다 Artifacts specified in the <dependencies> section will ALWAYS be included as a dependency of the child module(s)그들은뿐만 아니라 부모에 포함되어 있는지. 자녀에게는 의존성을 설정할 수 없지만 부모에게는 의존하지 않는 것 같습니다.
caduceus

54

Maven 사이트 의 문서 는 끔찍합니다. dependencyManagement가하는 일은 단순히 의존성 정의 (버전, 제외 등)를 상위 pom으로 이동 한 다음 자식 폼에서 groupId 및 artifactId를 넣어야합니다. 그게 다입니다 (부모 퐁 체인 등은 제외하지만 실제로는 복잡하지 않습니다)

Maven 사이트에서 'a', 'b', 'c'가비지를 모두 읽고 혼란스러워 한 후에 그들의 예를 다시 썼습니다. 따라서 공통 종속성 (betaShared)을 공유하는 2 개의 프로젝트 (proj1 및 proj2)가 있으면 해당 종속성을 상위 pom으로 이동할 수 있습니다. 당신이 그것에있는 동안, 당신은 또한 프로젝트에 적합한 경우에만 다른 의존성 (알파와 찰리)을 위로 이동할 수 있습니다. 따라서 이전 문장에 요약 된 상황에 대해 부모 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>

2
주제 외의 다른 질문 : 종속성 유형 "bar"는 무엇을 의미합니까? Maven 문서에서 예제 pom을 보았지만 정의를 찾을 수 없습니다. 나는 그것이 "전쟁"또는 "jar"의 오타라고 가정했지만, 당신과 같은 다른 예에서 그것을 봅니다.
NobodyMan

NobodyMan-다른 아카이브 유형의 자리 표시 자입니다. 'foo'를 사용하는 것과 같습니다. 또는 누군가 확장명이 'bar'인 사용자 정의 유형을 만든 경우 사용할 수 있습니다. 그리고 모호한 아카이브 유형이 많이 있습니다. jboss 서비스 아카이브 인 sar처럼.
MattC

귀하의 예는 매우 명확하며 설명서에서 직접 확인한 내용을 다시 확인합니다. Maven 프로젝트에 제출 했습니까? 귀하의 예를 연구 한 결과, 관련 프로젝트에 하위 프로젝트가 없으므로 종속성 선언 만 필요한 POM을 단순화 할 준비를하고 있습니다.
David A. Grey

글쎄, 의존성 관리 노드를 삭제하려고 할 때까지 의존성 트리에 간접적으로 접근하는 하위 POM에 대한 최소 버전을 설정할 수있게되었습니다. 예를 들어, javax.cache.cache-apI를 추적 할 때 전체적으로 사용될 수있는 상당히 최신 버전 1.0.0 (0.3.0)을 발견했습니다.
David A. Grey

이 설명은 pefect입니다.
스마트 코더

45

당신이 말한 것처럼; dependencyManagement하위 종속성 POM 파일의 참조를 단순화하여 모든 종속성 정보를 공통 POM 파일로 가져 오는 데 사용됩니다.

여러 하위 프로젝트에서 다시 입력하지 않으려는 여러 속성이있는 경우 유용합니다.

마지막으로 dependencyManagement여러 프로젝트에서 사용할 표준 버전의 아티팩트를 정의하는 데 사용할 수 있습니다.


4
따라서 종속성이 상속되지 않습니까? 어쨌든 자식 프로젝트의 폼폼에 선언해야합니까?
johnny-b-goode

6
예, 어쨌든 하위 프로젝트에서 버전을 지정하지 않고 선언해야합니다.
Pavel Vlasov

이 시나리오는 상위-하위 관계가있는 여러 Java 프로젝트에서 버전을 관리하려는 경우에 유용합니다.
Anuj Kumar

43

내 의견으로는 여전히 강조되지 않은 것은 원치 않는 상속 입니다.

다음은 증분 예입니다.

나는 내 parent퐁으로 선언합니다 .

<dependencies>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>19.0</version>
        </dependency>
</dependencies>

팔! 나는 그것을 가지고 Child A, Child BChild C모듈 :

  • 아동 치어에 의해 상속 된 허점
  • 관리 할 단일 장소
  • 아동 치어에서 아무것도 다시 선언 할 필요가 없습니다.
  • 나는 아직도 redelcare 및 재정의 할 수 있습니다 version 18.0A의 Child B내가 원하는 경우.

그러나에 구아바가 필요 Child C하지 않고 미래 Child DChild E모듈 모두에서 결과를 얻지 못하면 어떻게 될까요?

그들은 여전히 ​​그것을 상속받을 것이며 이것은 바람직하지 않습니다! 이것은 Java God Object 코드 냄새와 유사합니다. 여기서 클래스에서 유용한 비트와 원치 않는 많은 것들을 상속합니다.

여기가 시작 <dependencyManagement>됩니다. 이것을 부모 pom에 추가하면 모든 자식 모듈이 멈 춥니 . 따라서 당신이하는 강제 (않는이 필요로하는 각 개별 모듈로 이동하고 다시 선언 Child A하고 Child B버전 생각하지 않고).

그리고 분명히, 당신은 그것을하지 않기 Child C때문에 모듈은 마른 상태로 유지됩니다.


<dependencyManagement>에 언급 된 종속성이 상위 pom 프로젝트를 위해 다운 로딩됩니까?
Jaspreet Jolly

<dependencyManagement>부모 pom에서 사용하면 기본적으로 하위 폼에서 종속성이 상속되지 않습니까? 문서에서 maven.apache.org/guides/introduction/… 때문에 두 번째 사용법을 설명하는 동안 <dependencyManagement>기본적으로 상속되는 것처럼 보입니다. 한 줄에서 그들은 "maven이 프로젝트 B에서 실행될 때"b "가 사용되지 않더라도 pom에 지정된 버전에 관계없이 아티팩트 a, b, c 및 d의 버전 1.0이 사용됩니다"라고 말합니다. 프로젝트 B
chirag soni 2018 년

직접 시도해보십시오
Andrejs

17

차이 요약 몇 가지 답변이 있습니다 <depedencies><dependencyManagement>받는다는와 태그.

그러나 간결한 방법으로 아래에 자세히 설명 된 몇 가지 사항이 있습니다.

  1. <dependencyManagement>다양한 모듈에서 사용되는 모든 종속성 (자식 퐁 수준에서 사용)을 통합 할 수 있습니다. 명확성 , 중앙 종속성 버전 관리
  2. <dependencyManagement>필요에 따라 종속성을 쉽게 업그레이드 / 다운 그레이드 할 수 있습니다. 다른 시나리오에서는 모든 하위 폼 레벨에서 일관성을 유지해야합니다.
  3. <dependencies>태그에 제공된 종속성 은 항상 가져 오는 반면, <dependencyManagement>상위 pom에 제공된 종속성은 하위 pom에 <dependencies>태그에 해당 항목이있는 경우에만 가져옵니다 .

17

파티에 늦어서 미안해

mvn dependency:tree명령을 사용하여 차이점을 설명하려고합니다.

아래 예를 고려하십시오

부모 POM-내 프로젝트

<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>

자식 POM-데이터 모듈

<dependencies>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
    </dependency>
</dependencies>

하위 POM-앱 모듈 (추가 종속성이 없으므로 종속성을 비워 둡니다)

 <dependencies>
</dependencies>

mvn dependency:tree명령을 실행 하면 다음과 같은 결과가 나타납니다.

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 구아바 는 모든 모듈 (부모 포함)에서 종속성으로 표시되는 반면 아파치 커먼 은 데이터 모듈에서만 (부모 모듈이 아닌) 종속성으로 표시됩니다.


11

종속성이 최상위 pom의 dependencyManagement 요소에 정의 된 경우 하위 프로젝트는 종속성 버전을 명시 적으로 나열하지 않아도됩니다. 하위 프로젝트가 버전을 정의한 경우 최상위 POM의 dependencyManagement 섹션에 나열된 버전을 대체합니다. 즉, dependencyManagement 버전은 하위가 버전을 직접 선언하지 않은 경우에만 사용됩니다.


1
이 진술이 정확하지 않을 수 있다고 생각합니다. Maven의 종속성 관리 예제 (# 2)에서 버전이있는 상위 pom에 정의 된 종속성은 하위 pom에 지정된 버전을 재정의한다고 말합니다. "maven이 프로젝트 B 버전 1.0에서 이슈 a, b, c에서 실행될 때 , d는 해당 pom에 지정된 버전에 관계없이 사용됩니다. "
devdanke

@devdanke 적어도, Eclipse m2e는 경고 : 관리 버전 무시 중 ... ...을 발행합니다 .
GeroldBroser는 Monica를

4

부모 POM에서와의 주요 차이점은 다음 <dependencies><dependencyManagement>같습니다.

<dependencies>섹션에 지정된 아티팩트 는 항상 하위 모듈의 종속성으로 포함됩니다.

섹션에 지정된 아티팩트는 하위 모듈 자체의 섹션에도 지정된 경우에만 하위 모듈에 포함됩니다. 물어 보는 것이 왜 좋은가요? 상위에서 버전 및 / 또는 범위를 지정하고 하위 POM에서 종속성을 지정할 때이를 제외 할 수 있습니다. 이를 통해 각 하위 모듈에 버전을 지정하지 않고도 하위 모듈의 종속성에 통합 버전을 사용할 수 있습니다.


4

내 말로, 당신 parent-project은 당신이 두 종류의 의존성을 제공하는 데 도움이됩니다.

  • 암시 적 종속성 : <dependencies>섹션에 정의 된 모든 종속성 parent-project은 모든child-projects
  • 명시 적 종속성 :에 적용 할 종속성을 선택할 수 있습니다 child-projects. 따라서 <dependencyManagement>섹션을 사용하여 다른에 사용할 모든 종속성을 선언하십시오 child-projects. 가장 중요한 것은이 섹션 <version>에서을 (를) 다시 선언 할 필요 가 없도록 정의하는 것입니다 child-project.

<dependencyManagement>당신이 당신의 의존성의 버전을 중앙 집중 지원함으로써 단지 유용 내 관점에서은 (만약 내가 잘못 정정 해줘). 일종의 도우미 기능과 같습니다.


1

Eclipse에는의 기능이 하나 더 있습니다 dependencyManagement. dependencies그것없이 사용될 때 , 발견되지 않은 의존성은 pom 파일에서 발견됩니다. 경우 dependencyManagement사용하는 경우, 미해결 의존성은 치어 파일에서 주목 남아 오류는 자바 파일 만 나타납니다. (수입 등)


1

이 둘의 차이점은 Maven 웹 사이트 문서에서 사용 가능한 dependencyManagement 요소에 대한 필요하고 충분한 정의로 보이는 것이 가장 좋습니다.

의존성 관리

"이 프로젝트에서 상속 된 프로젝트의 기본 종속성 정보.이 섹션의 종속성은 즉시 해결되지 않습니다. 대신이 POM에서 파생 된 POM이 일치하는 groupId 및 artifactId,이 섹션의 버전 및 기타 값으로 설명 된 종속성을 선언 할 때 "지정되지 않은 경우 해당 종속성에 사용됩니다." [ https://maven.apache.org/ref/3.6.1/maven-model/maven.html ]

다른 페이지에서 사용 가능한 추가 정보와 함께 읽어야합니다.

".. dependencyManagement 섹션에 대한 종속성 참조를 일치시키기위한 최소한의 정보 집합은 실제로 {groupId, artifactId, type, classifier}입니다. 대부분의 경우 이러한 종속성은 분류자가없는 jar 아티팩트를 나타냅니다. 유형 필드의 기본값은 jar이고 기본 분류기는 null이므로 ID 세트를 {groupId, artifactId}로 줄입니다.” [ https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html ]

따라서 버전뿐만 아니라 groupId, artifactId, type, classifier 이외의 종속성 요소의 모든 하위 요소 (범위, 제외 등)를 해당 시점에서 잠금 / 기본값으로 사용할 수 있습니다. 그 이후에 dependencyElement 내에 종속성을 지정합니다. type 및 classifier 하위 요소 (종종 하위 요소를 확인하려면 첫 번째 인용 된 웹 페이지 참조)와의 종속성을 각각 jar가 아닌 null이 아닌 것으로 지정한 경우 {groupId, artifactId, classifier, type}이 필요합니다. dependencyManagement 요소에서 비롯된 상속의 모든 시점에서 해당 종속성을 참조 (해결)합니다. 그렇지 않으면, 분류 자 ​​및 유형 (각각 jar 및 널)의 기본값을 대체하지 않으려는 경우 {groupId, artifactId}로 충분합니다. 기본적으로이 정의에서 좋은 키워드입니다. 하위 요소 (groupId 이외)

따라서 일부 dependencyManagement 요소에 대한 참조이든 독립형이든 상관없이 dependencyManagement 외부의 모든 종속성 요소가 즉시 해결됩니다 (즉, 로컬 저장소에 설치되어 클래스 경로에 사용 가능함).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.