Ivy 的配置是一項極具彈性的機制,它讓你能為同一模組定義不同的「使用視圖」。有人形容:「使用 Ivy 卻不使用配置,就像品嚐乾酪卻不飲用旁邊的 Chateau Margaux 1976!」配置能將制品依賴關係精確劃分,避免不必要的傳遞依賴污染。
專案位於 src/example/configurations/multi-projects,包含兩個模組:
<ivy-module version="1.0">
<info organisation="org.apache" module="filter-framework"/>
<configurations>
<conf name="api" description="only provide filter framework API"/>
<conf name="homemade-impl" extends="api" description="provide a home made implementation"/>
<conf name="cc-impl" extends="api" description="provide an implementation using apache commons collections"/>
<conf name="test" extends="cc-impl" visibility="private" description="for testing our framework"/>
</configurations>
<publications>
<artifact name="filter-api" type="jar" conf="api" ext="jar"/>
<artifact name="filter-hmimpl" type="jar" conf="homemade-impl" ext="jar"/>
<artifact name="filter-ccimpl" type="jar" conf="cc-impl" ext="jar"/>
</publications>
<dependencies>
<dependency org="commons-collections" name="commons-collections" rev="3.1" conf="cc-impl->default"/>
<dependency org="junit" name="junit" rev="3.8" conf="test->default"/>
</dependencies>
</ivy-module>
homemade-impl 和 cc-impl 都 extends="api",意味著它們自動包含 API 制品。<publications> 將每個 JAR 精確綁定到對應配置,消費者可按需獲取。commons-collections 僅在 cc-impl 配置下需要;junit 僅在私有 test 配置下需要,不會外洩。執行 ant(預設 target 為 publish)後,Ivy 解析報告顯示各配置解析到的模組數與制品數:
| conf | number| search|dwnlded|evicted|| number|dwnlded|
| api | 0 | 0 | 0 | 0 || 0 | 0 |
| homemade-impl | 0 | 0 | 0 | 0 || 0 | 0 |
| cc-impl | 1 | 1 | 0 | 0 || 1 | 1 |
| test | 2 | 2 | 0 | 0 || 2 | 2 |
三個 JAR(filter-api.jar、filter-hmimpl.jar、filter-ccimpl.jar)成功發布到本地儲存庫(${user.home}/.ivy2/local)。
<ivy-module version="1.0">
<info organisation="org.apache" module="myapp"/>
<configurations>
<conf name="build" visibility="private" description="compilation only need api jar"/>
<conf name="noexternaljar" description="use only company jar"/>
<conf name="withexternaljar" description="use company jar and third party jars"/>
</configurations>
<dependencies>
<dependency org="org.apache" name="filter-framework" rev="latest.integration"
conf="build->api; noexternaljar->homemade-impl; withexternaljar->cc-impl"/>
</dependencies>
</ivy-module>
依賴宣告中的 conf 屬性使用「消費者配置 -> 提供者配置」的映射語法:
build -> api:編譯時只需 API。noexternaljar -> homemade-impl:執行時使用無外部依賴的自製實作。withexternaljar -> cc-impl:執行時使用需 Commons Collections 的實作。消費者完全不需知道具體制品名稱,由提供者的 <publications> 決定交付什麼檔案。
Ant 的 resolve target 使用 <ivy:retrieve pattern="${ivy.lib.dir}/[conf]/[artifact].[ext]"/>,將制品按配置分目錄存放:
lib/build/filter-api.jar
lib/noexternaljar/filter-api.jar
lib/noexternaljar/filter-hmimpl.jar
lib/withexternaljar/commons-collections.jar
lib/withexternaljar/filter-api.jar
lib/withexternaljar/filter-ccimpl.jar
執行 ant run-cc(使用 Commons Collections 實作)與 ant run-hm(使用自製實作)均成功,輸出結果一致但底層實作類別不同,完美展示配置切換的威力。
配置是 Ivy 區別於其他依賴管理工具的核心優勢。撰寫可重用模組時,善用配置讓消費者精準獲取所需,無須在依賴區塊手工列舉制品。請盡可能在專案中採用配置,發揮 Ivy 的最大效能。