架构必修课:使用Bom管理依赖项

发表于:2023-9-13 09:47

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:迷路的架构师    来源:今日头条

#
架构
  如果你使用过 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将会存在很多问题,如下:
  版本冲突:当不同的模块或项目中使用相同的依赖项但版本不一致时,可能会发生版本冲突。可能导致编译错误、运行时异常或不可预测的行为。没有统一的依赖版本管理机制,开发人员需要手动处理版本冲突,增加了工作量和复杂性。
  配置繁琐:在每个模块或项目中单独指定依赖的版本号会导致配置繁琐。当需要更新或更改依赖版本时,必须在每个地方进行修改,容易遗漏或出错。这样的配置过程耗费时间且容易引入错误。
  不一致的依赖环境:每个模块或项目都有自己独立的依赖配置,可能会导致不一致的依赖环境。这种不一致性可能导致测试和部署问题,以及与其他团队成员之间的协作困难。
  难以维护和更新:没有集中的依赖管理机制,使得维护和更新依赖项变得困难。当需要升级依赖版本或添加新的依赖时,需要在多个模块或项目中进行手动操作,容易出错并带来额外的工作量。
  缺乏可视化和统一性:没有BOM作为依赖清单,开发人员可能缺乏对项目整体依赖关系和版本一致性的全局视图。这使得项目管理和团队协作变得更加困难。
  举一个例子,app项目引入guava:31.1版本,又引入了lib,lib中依赖了guava:25.0,这时候将会存在两个版本,如果还依赖了其他lib,其中又依赖了其他的guava版本,那么项目中同一个依赖将存在非常多的版本,难以管理。且与其他项目组协作时,版本不统一可能导致很多编译错误。
  比如在guava:25.0中的这段代码:
  public class FutureStub {
      public static Future<String> 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示例:
  首先,在项目的根目录下创建一个名为dependencies.gradle的文件,用于定义BOM(Bill of Materials):
  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")
      }
  }
  在项目的build.gradle文件中,引入BOM并应用到模块中,并定义Maven发布任务:
  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
  }
  运行 publishToMavenRepository 任务来生成 BOM 文件并发布到 Maven 仓库:
  ./gradlew publishToMavenRepository
  这样就完成了Bom的定义和发布,可以在Bom中统一管理项目中的依赖项版本,并可以让其他团队使用这个Bom。
  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号