Maven中optional和exclusion的区别
    
  
      
      
     
    
      
        用了那么久的Maven,我们都知道Maven的依赖关系具有传递性,比如A依赖B,B依赖C,那么A也依赖于C,具体在项目中的表现见图:

上述依赖在pom.xml中的关系是这样的:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 
 | C(cc-spring-boot-starter-autoconfigure):<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter</artifactId>
 </dependency>
 
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-configuration-processor</artifactId>
 </dependency>
 
 B(cc-spring-boot-starter):
 <dependency>
 <groupId>cc.lu</groupId>
 <artifactId>cc-spring-boot-starter-autoconfigure</artifactId>
 </dependency>
 
 A(cc-starter-demo):
 <dependency>
 <groupId>cc.lu</groupId>
 <artifactId>cc-spring-boot-starter</artifactId>
 </dependency>
 
 | 
但是在实际的应用中,项目A可能不是必须依赖C,如果不做处理的话,最终会让项目A非常的臃肿,打的包非常大。在Maven中,提供了两种方式管理非必须的依赖关系:可选依赖(Optional Dependencies)和依赖排除(Dependency Exclusion)。
 一、依赖排除(exclusion)
在项目A中,不需要依赖项目C中的org.springframework.boot:spring-boot-configuration-processor包,但是项目B仍然需要依赖它,也就是说我们需要在项目A中将这个包排除掉,但是又不能影响其他项目对这个包的依赖,关系图为:

我们只要在需要排除的项目A中,对依赖的dependency加上exclusion并指定要排除包的groupId和artifactId即可,不需要指定版本号,若上有项目依赖了多个相同包的不同版本,在这里会全部都排除掉。对应的pom.xml文件内容:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 
 | C(cc-spring-boot-starter-autoconfigure):<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter</artifactId>
 </dependency>
 
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-configuration-processor</artifactId>
 </dependency>
 
 B(cc-spring-boot-starter):
 <dependency>
 <groupId>cc.lu</groupId>
 <artifactId>cc-spring-boot-starter-autoconfigure</artifactId>
 </dependency>
 
 A(cc-starter-demo):
 <dependency>
 <groupId>cc.lu</groupId>
 <artifactId>cc-spring-boot-starter</artifactId>
 <exclusions>
 <exclusion>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-configuration-processor</artifactId>
 </exclusion>
 </exclusions>
 </dependency>
 
 | 
 二、可选依赖(optional)
可选依赖就厉害了,只允许在当前项目使用,从不往下传递,下游项目要是想使用的话需要自己重新引入,比如org.springframework.boot:spring-boot-configuration-processor是自动生成配置参数的功能性包,也仅仅就在生成参数声明的时候用到,没必要往下传递,那么这种就需要在项目C中做控制了,严禁它依赖的包向下传递。

我们在项目C中将org.springframework.boot:spring-boot-configuration-processor的optional选项设置为true,默认为false(true: 不向下传递,false: 向下传递),在org.mybatis:mybatis包中有大量的应用,可以自行查看一下,这里放张图:
 
项目pom.xml内容如下,关注一下项目C的:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 
 | C(cc-spring-boot-starter-autoconfigure):<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter</artifactId>
 </dependency>
 
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-configuration-processor</artifactId>
 <optional>true</optional>
 </dependency>
 
 B(cc-spring-boot-starter):
 <dependency>
 <groupId>cc.lu</groupId>
 <artifactId>cc-spring-boot-starter-autoconfigure</artifactId>
 </dependency>
 
 A(cc-starter-demo):
 <dependency>
 <groupId>cc.lu</groupId>
 <artifactId>cc-spring-boot-starter</artifactId>
 </dependency>
 
 | 
 总结
在Maven依赖管理中,有依赖排除和可选依赖两种方式可以屏蔽项目不需要的包,区别是只想在当前项目使用的话就用可选依赖,若在当前项目不想使用依赖的包中的某个包,则用依赖排除。
- 可选依赖是在第一级被引用的地方使用optional标签声明
- 依赖排除是在具体不需要依赖的那一级(也可以理解为最后一级)使用exclusion控制