Maven中optional和exclusion的区别

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

image-20200423122520591

上述依赖在pom.xml中的关系是这样的:

1
2
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中将这个包排除掉,但是又不能影响其他项目对这个包的依赖,关系图为:

image-20200423122841522

我们只要在需要排除的项目A中,对依赖的dependency加上exclusion并指定要排除包的groupId和artifactId即可,不需要指定版本号,若上有项目依赖了多个相同包的不同版本,在这里会全部都排除掉。对应的pom.xml文件内容:

1
2
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中做控制了,严禁它依赖的包向下传递。

image-20200423124556099

我们在项目C中将org.springframework.boot:spring-boot-configuration-processor的optional选项设置为true,默认为false(true: 不向下传递,false: 向下传递),在org.mybatis:mybatis包中有大量的应用,可以自行查看一下,这里放张图:

image-20200423125547745

项目pom.xml内容如下,关注一下项目C的:

1
2
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依赖管理中,有依赖排除和可选依赖两种方式可以屏蔽项目不需要的包,区别是只想在当前项目使用的话就用可选依赖,若在当前项目不想使用依赖的包中的某个包,则用依赖排除。

  1. 可选依赖是在第一级被引用的地方使用optional标签声明
  2. 依赖排除是在具体不需要依赖的那一级(也可以理解为最后一级)使用exclusion控制