一、什么是BOM?
Bill of Materials (BOM)物料清单,实际上就是一个普通的pom文件,在pom文件中只定义dependencyManagement版本依赖管理,用于管理项目依赖的所有jar包;有利于包版本的统一,降低由于版本不一致导致的冲突;有利于降低配置的复杂度,提升开发效率。
二、BOM定义经典案例
<dependencyManagement>
<dependencies>
<dependency>
<dependency>
<groupId>io.github.mingyang66</groupId>
<artifactId>emily-dependencies</artifactId>
<version>4.4.8</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependency>
</dependencies>
</dependencyManagement>
-
spring-boot-dependencies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
- spring-cloud-dependencies https://github.com/spring-cloud/spring-cloud-release
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
-
feign-bom
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-bom</artifactId>
<version>??feign.version??</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
三、基于官方文档案例分析
https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html
- 定义一个名为bom的module,pom定义如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>bom</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<properties>
<project1Version>1.0.0</project1Version>
<project2Version>1.0.0</project2Version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.test</groupId>
<artifactId>project1</artifactId>
<version>${project1Version}</version>
</dependency>
<dependency>
<groupId>com.test</groupId>
<artifactId>project2</artifactId>
<version>${project2Version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<module>parent</module>
</modules>
</project>
- 上述bom模块的子模块parent的pom定义如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.test</groupId>
<version>1.0.0</version>
<artifactId>bom</artifactId>
</parent>
<groupId>com.test</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<module>project1</module>
<module>project2</module>
</modules>
</project>
- 定义实际的项目project1、project2
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.test</groupId>
<version>1.0.0</version>
<artifactId>parent</artifactId>
</parent>
<groupId>com.test</groupId>
<artifactId>project1</artifactId>
<version>${project1Version}</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
</dependencies>
</project>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.test</groupId>
<version>1.0.0</version>
<artifactId>parent</artifactId>
</parent>
<groupId>com.test</groupId>
<artifactId>project2</artifactId>
<version>${project2Version}</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</dependency>
</dependencies>
</project>
- 如下是使用上述定义的BOM POM文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>use</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.test</groupId>
<artifactId>bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.test</groupId>
<artifactId>project1</artifactId>
</dependency>
<dependency>
<groupId>com.test</groupId>
<artifactId>project2</artifactId>
</dependency>
</dependencies>
</project>
最后,在创建import dependencies依赖项项目时,请注意以下事项:
- 不要尝试导入当前POM子模块中定义的pom,尝试这样做将导致构建失败,因为它将无法定位POM.
- 切勿将parent POM声明为import POM,这样将无法解决循环问题,将抛出异常。
- 当引用的POM具有依赖传递关系的工件时,项目需要将这些工件的版本指定为托管依赖关系。不这样做会导致构建失败,因为工件可能没有指定版本。(在任何情况下,这都应该被视为一种最佳实践,因为它可以防止工件的版本从一个版本更改到下一个版本)。
四、真实实践案例
开源SDK:https://github.com/mingyang66/spring-parent
- 案例目录结构
emily-build-parent
|--emily-dependencies
| |-pom.xml
|--emily-parent
| |-pom.xml
|--emily-project
| |-oceansky-captcha
| |-oceansky-common
| |-oceansky-date
| |-oceansky-json
| |-oceansky-jwt
| |-oceansky-language
| |-oceansky-logger
| |-oceansky-sensitive
|--emily-spring-boot-project
| |-emily-spring
| |-emily-spring-boot-core
| |-emily-spring-boot-datasource
| |-emily-spring-boot-logger
| |-emily-spring-boot-rabbitmq
| |-emily-spring-boot-redis
| |-emily-spring-boot-starter
| |-emily-spring-boot-transfer
| |-emily-spring-cloud-starter
|--emily-spring-boot-samples
| |-demo-spring-boot-boot
| |-demo-spring-cloud-boot
- 此案例实现了maven的版本父子模块值传递的友好管理实现;
- emily-dependencies是定义为Bill Of Materials(BOM) POM,定义当前项目依赖的jar及当前项目module的依赖管理;
- emily-parent的POM定义为emily-dependencies的子POM,内部只定义了emily-dependencies的依赖管理,不会发生循环依赖异常问题;
- emily-project和emily-spring-boot-project都是具体的子项目module实现,其POM的parent都定义为emily-parent;
- emily-spring-boot-samples是测试module,具体测试依赖BOM的使用方式;