9.4.2. 可选依赖

假定你正在开发一个类库 ,该类库提供高速缓存行为。你想要使用一些已存在的能够提供文件系统快速缓存和分布式快速缓存的类库,而非从空白开始写自己的快速缓存系统。再假定你想要能让最终用户选择使用文件系统高速缓存或者内存分布式高速缓存。为了缓存文件系统,你会要使用免费的类库如EHCache(http://ehcache.sourceforge.net/),为了分布式内存缓存,你想要使用免费的类库如SwarmCache(http://swarmcache.sourceforge.net/)。你将编写一个接口,并且创建一个可以被配置成使用EHCache或者SwarmCache的类库,但是你想要避免为所有依赖于你类库的项目添加全部这两个缓存类库的的依赖。

换句话说,编译这个项目的时候你需要两个依赖类库,但是你不希望在使用你类库的项目中,这两个依赖类库同时作为传递性运行时依赖出现。你可以使用如Example 9.4, “声明可选依赖”中的可选依赖来完成这个任务。

Example 9.4. 声明可选依赖

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.sonatype.mavenbook</groupId>
  <artifactId>my-project</artifactId>
  <version>1.0.0</version>
  <dependencies>
    <dependency>
      <groupId>net.sf.ehcache</groupId>
      <artifactId>ehcache</artifactId>
      <version>1.4.1</version>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>swarmcache</groupId>
      <artifactId>swarmcache</artifactId>
      <version>1.0RC2</version>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.13</version>
    </dependency>
  </dependencies>
</project>

在你将这些依赖声明为可选之后,你就需要在依赖于my-project的项目中显式的引用对应的依赖。例如,如果你正编写一个应用,它依赖于my-project,并且想要使用EHCache实现,你就需要在你项目添加如下的dependency元素。

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.sonatype.mavenbook</groupId>
  <artifactId>my-application</artifactId>
  <version>1.0.0</version>
  <dependencies>
    <dependency>
      <groupId>org.sonatype.mavenbook</groupId>
      <artifactId>my-project</artifactId>
      <version>1.0.0</version>
    </dependency>
    <dependency>
      <groupId>net.sf.ehcache</groupId>
      <artifactId>swarmcache</artifactId>
      <version>1.4.1</version>
    </dependency>
  </dependencies>
</project>

在理想的世界中,你不需要使用可选依赖。你可以将EHCache相关的代码放到my-project-ehcache子模块中,将SwarmCache相关的代码放到my-project-swarmcache子模块中,而非创建一个带有一系列可选依赖的大项目。这样,其它项目就可以只引用特定实现的项目,发挥传递性依赖的功效,而不用去引用my-project项目,再自己声明特定的依赖。