Gradle依賴沖突解決

通過gradle -q [項(xiàng)目名]:dependencies命令查看依賴樹,可以比較直觀的看到?jīng)_突。Gradle 可以通過分析該依賴樹獲取所有依賴以及依賴的依賴和依賴的依賴的依賴,為了更加直觀的表述,可以通過下面的輸出結(jié)果了解。

+--- org.springframework:spring-web:4.3.4.RELEASE
|    |    +--- org.springframework:spring-aop:4.3.4.RELEASE
|    |    +--- org.springframework:spring-beans:4.3.4.RELEASE
|    |    +--- org.springframework:spring-context:4.3.4.RELEASE
|    |    \--- org.springframework:spring-core:4.3.4.RELEASE
+--- org.springframework:spring-aop:4.5

可以看到,我們的項(xiàng)目依賴了spring-web,然而spirng-web卻依賴了一眾spring的全家桶,借助Gradle的傳遞性依賴特性,你無需再你的腳本中把這些依賴都聲明一遍,你只需要簡單的一行,Gradle便會(huì)幫你將傳遞性依賴一起下載下來。

但是我在項(xiàng)目中顯式聲明了spring-aop:4.5,而spring-web又帶來的spring-aop:4.3.4.RELEASE,那么就會(huì)造成項(xiàng)目中的依賴沖突,啟動(dòng)報(bào)錯(cuò)。

下面通過分析如下案例來說明如何解決依賴沖突:

dependencies {
   androidTestCompile('com.android.support.test:runner:0.2')
   androidTestCompile('com.android.support.test:rules:0.2')
   androidTestCompile('com.android.support.test.espresso:espresso-core:2.1')
}

運(yùn)行g(shù)radle dependencies的結(jié)果如下,可以看到每個(gè)包的依賴項(xiàng)都被遞歸分析并添加進(jìn)來。

+--- com.android.support.test:runner:0.2
|    +--- junit:junit-dep:4.10
|    |    \--- org.hamcrest:hamcrest-core:1.1
|    +--- com.android.support.test:exposed-instrumentation-api-publish:0.2
|    \--- com.android.support:support-annotations:22.0.0
+--- com.android.support.test:rules:0.2
|    \--- com.android.support.test:runner:0.2 (*)
\--- com.android.support.test.espresso:espresso-core:2.1
     +--- com.android.support.test:rules:0.2 (*)
     +--- com.squareup:javawriter:2.1.1
     +--- org.hamcrest:hamcrest-integration:1.1
     |    \--- org.hamcrest:hamcrest-core:1.1
     +--- com.android.support.test.espresso:espresso-idling-resource:2.1
     +--- org.hamcrest:hamcrest-library:1.1
     |    \--- org.hamcrest:hamcrest-core:1.1
     +--- javax.inject:javax.inject:1
     +--- com.google.code.findbugs:jsr305:2.0.1
     +--- com.android.support.test:runner:0.2 (*)
     +--- javax.annotation:javax.annotation-api:1.2
     \--- org.hamcrest:hamcrest-core:1.1

Transitive

Transitive用于自動(dòng)處理子依賴項(xiàng),默認(rèn)為true,gradle自動(dòng)添加子依賴項(xiàng),形成一個(gè)多層樹形結(jié)構(gòu);設(shè)置為false,則需要手動(dòng)添加每個(gè)依賴項(xiàng)。

【統(tǒng)一指定transitive】

可以給dependencies統(tǒng)一指定transitive為false,再次執(zhí)行dependencies可以看到如下結(jié)果。

configurations.all {
   transitive = false
}
dependencies {
   androidTestCompile('com.android.support.test:runner:0.2')
   androidTestCompile('com.android.support.test:rules:0.2')
   androidTestCompile('com.android.support.test.espresso:espresso-core:2.1')
}
+--- com.android.support.test:runner:0.2
+--- com.android.support.test:rules:0.2
\--- com.android.support.test.espresso:espresso-core:2.1

但是這樣的話這三個(gè)jar包所依賴的jar包就要手動(dòng)添加進(jìn)來,否則運(yùn)行就會(huì)報(bào)錯(cuò),這三個(gè)jar包中的某些類和方法無法找到。

【單獨(dú)指定依賴項(xiàng)的transitive】

dependencies {
   androidTestCompile('com.android.support.test:runner:0.2')
   androidTestCompile('com.android.support.test:rules:0.2')
   androidTestCompile('com.android.support.test.espresso:espresso-core:2.1') {
       transitive = false
   }
}

Force

有時(shí)候你可能僅僅是需要強(qiáng)制使用某個(gè)統(tǒng)一的依賴版本,而不是排除他們,那么此時(shí)force就該登場了。force強(qiáng)制設(shè)置某個(gè)模塊的版本。

configurations.all {
   resolutionStrategy {
       force 'org.hamcrest:hamcrest-core:1.3'
   }
}
dependencies {
   androidTestCompile('com.android.support.test:runner:0.2')
   androidTestCompile('com.android.support.test:rules:0.2')
   androidTestCompile('com.android.support.test.espresso:espresso-core:2.1')
}

可以看到,原本對(duì)hamcrest-core 1.1的依賴,全部變成了1.3。

+--- com.android.support.test:runner:0.2
|    +--- junit:junit-dep:4.10
|    |    \--- org.hamcrest:hamcrest-core:1.1 -> 1.3
|    +--- com.android.support.test:exposed-instrumentation-api-publish:0.2
|    \--- com.android.support:support-annotations:22.0.0
+--- com.android.support.test:rules:0.2
|    \--- com.android.support.test:runner:0.2 (*)
\--- com.android.support.test.espresso:espresso-core:2.1
     +--- com.android.support.test:rules:0.2 (*)
     +--- com.squareup:javawriter:2.1.1
     +--- org.hamcrest:hamcrest-integration:1.1
     |    \--- org.hamcrest:hamcrest-core:1.1 -> 1.3
     +--- com.android.support.test.espresso:espresso-idling-resource:2.1
     +--- org.hamcrest:hamcrest-library:1.1
     |    \--- org.hamcrest:hamcrest-core:1.1 -> 1.3
     +--- javax.inject:javax.inject:1
     +--- com.google.code.findbugs:jsr305:2.0.1
     +--- com.android.support.test:runner:0.2 (*)
     +--- javax.annotation:javax.annotation-api:1.2
     \--- org.hamcrest:hamcrest-core:1.1 -> 1.3

Exclude

有些時(shí)候你可能需要排除一些傳遞性依賴中的某個(gè)模塊,此時(shí)便不能靠單純的關(guān)閉依賴傳遞特性來解決了。這時(shí)exclude就該登場了,如果說Transitive徹底的解決了傳遞問題,那么exclude則是部分解決了傳遞問題。Exclude可以設(shè)置不編譯指定的模塊

configurations {
   all*.exclude group: 'org.hamcrest', module: 'hamcrest-core'
}
dependencies {
   androidTestCompile('com.android.support.test:runner:0.2')
   androidTestCompile('com.android.support.test:rules:0.2')
   androidTestCompile('com.android.support.test.espresso:espresso-core:2.1')
}
+--- com.android.support.test:runner:0.2
|    +--- junit:junit-dep:4.10
|    +--- com.android.support.test:exposed-instrumentation-api-publish:0.2
|    \--- com.android.support:support-annotations:22.0.0
+--- com.android.support.test:rules:0.2
|    \--- com.android.support.test:runner:0.2 (*)
\--- com.android.support.test.espresso:espresso-core:2.1
     +--- com.android.support.test:rules:0.2 (*)
     +--- com.squareup:javawriter:2.1.1
     +--- org.hamcrest:hamcrest-integration:1.1
     +--- com.android.support.test.espresso:espresso-idling-resource:2.1
     +--- org.hamcrest:hamcrest-library:1.1
     +--- javax.inject:javax.inject:1
     +--- com.google.code.findbugs:jsr305:2.0.1
     +--- com.android.support.test:runner:0.2 (*)
     \--- javax.annotation:javax.annotation-api:1.2

【單獨(dú)使用group或module參數(shù)】

exclude后的參數(shù)有g(shù)roup和module,可以分別單獨(dú)使用,會(huì)排除所有匹配項(xiàng)。例如下面的腳本匹配了所有的group為’com.android.support.test’的模塊。

configurations {
   all*.exclude group: 'com.android.support.test'
}
dependencies {
   androidTestCompile('com.android.support.test:runner:0.2')
   androidTestCompile('com.android.support.test:rules:0.2')
   androidTestCompile('com.android.support.test.espresso:espresso-core:2.1')
}
\--- com.android.support.test.espresso:espresso-core:2.1
     +--- com.squareup:javawriter:2.1.1
     +--- org.hamcrest:hamcrest-integration:1.1
     |    \--- org.hamcrest:hamcrest-core:1.1
     +--- com.android.support.test.espresso:espresso-idling-resource:2.1
     +--- org.hamcrest:hamcrest-library:1.1
     |    \--- org.hamcrest:hamcrest-core:1.1
     +--- javax.inject:javax.inject:1
     +--- com.google.code.findbugs:jsr305:2.0.1
     +--- javax.annotation:javax.annotation-api:1.2
     \--- org.hamcrest:hamcrest-core:1.1

【單獨(dú)給某個(gè)模塊指定exclude】

dependencies {
   androidTestCompile('com.android.support.test:runner:0.2')
   androidTestCompile('com.android.support.test:rules:0.2')
   androidTestCompile('com.android.support.test.espresso:espresso-core:2.1') {
       exclude group: 'org.hamcrest'
   }
}
+--- com.android.support.test:runner:0.2
|    +--- junit:junit-dep:4.10
|    |    \--- org.hamcrest:hamcrest-core:1.1
|    +--- com.android.support.test:exposed-instrumentation-api-publish:0.2
|    \--- com.android.support:support-annotations:22.0.0
+--- com.android.support.test:rules:0.2
|    \--- com.android.support.test:runner:0.2 (*)
\--- com.android.support.test.espresso:espresso-core:2.1
     +--- com.android.support.test:rules:0.2 (*)
     +--- com.squareup:javawriter:2.1.1
     +--- com.android.support.test.espresso:espresso-idling-resource:2.1
     +--- javax.inject:javax.inject:1
     +--- com.google.code.findbugs:jsr305:2.0.1
     +--- com.android.support.test:runner:0.2 (*)
     \--- javax.annotation:javax.annotation-api:1.2

【重要說明】

使用exclude排除依賴的時(shí)候只能排除jar包下面的直接依賴,而不能跨級(jí)排除,否則排除是不生效的。如案例中,我想要排除com.android.support.test:runner:0.2下的com.android.support:support-annotations:22.0.0

+--- com.android.support.test:runner:0.2
|    +--- junit:junit-dep:4.10
|    |    \--- org.hamcrest:hamcrest-core:1.1
|    +--- com.android.support.test:exposed-instrumentation-api-publish:0.2
|    \--- com.android.support:support-annotations:22.0.0

如果我像下面這樣寫是無法排除該jar包的:

androidTestCompile('com.android.support.test:runner:0.2'){
   exclude group: 'support-annotations'
}

依賴的結(jié)果仍然是上面的依賴樹。這樣的情況下只能逐級(jí)排除:

androidTestCompile('com.android.support.test:runner:0.2'){
   exclude group: 'exposed-instrumentation-api-publish'
}

androidTestCompile(' com.android.support.test:exposed-instrumentation-api-publish:0.2'){
   exclude group: 'support-annotations'
}

因?yàn)槲覀兣懦?code>com.android.support.test:runner:0.2所要依賴的exposed-instrumentation-api-publish,所以我們后面還得手工添加進(jìn)來,并在exposed-instrumentation-api-publish排除掉support-annotations依賴。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容