如果你使用过 Spring Boot,应该能注意到我们只需要声明使用的库即可,而不必指定版本。如下所示:
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'javax.cache:cache-api'
implementation 'jakarta.xml.bind:jakarta.xml.bind-api'
runtimeOnly 'org.springframework.boot:spring-boot-starter-actuator'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'org.postgresql:postgresql'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
那么这是如何实现的呢?答案当然是使用Bom进行版本管理。
为什么要使用Bom?
不使用Bom将会存在很多问题,如下:
举一个例子,app项目引入guava:31.1版本,又引入了lib,lib中依赖了guava:25.0,这时候将会存在两个版本,如果还依赖了其他lib,其中又依赖了其他的guava版本,那么项目中同一个依赖将存在非常多的版本,难以管理。且与其他项目组协作时,版本不统一可能导致很多编译错误。
比如在guava:25.0中的这段代码:
public class FutureStub {
public static Future ofString(String s) {
doSomethingFunOnPurpose();
return CompletableFuture.completedFuture(s);
}
private static void doSomethingFunOnPurpose() {
Futures.immediateCheckedFuture(new Object());
}
}
public class App {
public static void main(String[] args) throws Exception {
final var future = FutureStub.ofString("Hello Maven BOM");
System.out.println(future.get());
}
}
在App类中的main函数对FutureStub.ofString方法进行调用,这段代码在guava:25.0中运行良好,但在当前App项目中就会报错,原因是该方法在guava:28后就已经废弃了。
那么要如何统一管理Bom呢?可以使用 Gradle 或者 Maven。
Gradle Bom示例:
ext {
// 定义BOM版本
bomVersion = '1.0.0'
// 定义依赖项的版本号
dependencies = [
'dependency1': '1.2.3',
'dependency2': '4.5.6',
// 添加更多依赖项...
]
}
// 创建BOM配置
configurations {
bom
}
// 生成BOM文件
task generateBom {
outputs.file("dependencies.bom")
doLast {
def bomFile = new File(outputs.files.singleFile, "dependencies.bom")
bomFile.text = configurations.bom.getResolvedConfiguration().getFirstLevelModuleDependencies().collect { dep ->
"${dep.moduleGroup}:${dep.moduleName}:${dep.moduleVersion}"
}.join("n")
}
}
apply from: 'dependencies.gradle'
plugins {
id 'maven-publish'
}
// 发布到Maven仓库
publishing {
repositories {
maven {
url "https://your.maven.repository.url" // 替换为实际的Maven仓库地址
credentials {
username 'your-username' // 替换为Maven仓库的用户名
password 'your-password' // 替换为Maven仓库的密码或API密钥
}
}
}
publications {
mavenBom(MavenPublication) {
artifactId 'your-bom-artifact' // 替换为您的BOM的Artifact ID
version bomVersion
groupId 'your.group.id' // 替换为您的BOM的Group ID
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
dependencies.each { depName, depVersion ->
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', 'your.dependency.group.id') // 替换为实际的依赖项的Group ID
dependencyNode.appendNode('artifactId', depName)
dependencyNode.appendNode('version', depVersion)
}
}
}
}
}
// 发布任务
task publishToMavenRepository {
dependsOn generateBom
dependsOn publish
}
./gradlew publishToMavenRepository
这样就完成了Bom的定义和发布,可以在Bom中统一管理项目中的依赖项版本,并可以让其他团队使用这个Bom。