前提

这篇文章是《SpringBoot2.x入门》专辑的第1篇文章,使用的SpringBoot版本为2.3.1.RELEASEJDK版本为1.8

主要梳理一下SpringBoot2.x的依赖关系和依赖的版本管理,依赖版本管理是开发和管理一个SpringBoot项目的前提。

SpringBoot其实是通过starter的形式,对spring-framework进行装箱,消除了(但是兼容和保留)原来的XML配置,目的是更加便捷地集成其他框架,打造一个完整高效的开发生态。

SpringBoot依赖关系

因为个人不太喜欢Gradle,所以下文都以Maven举例。

SpringCloud的版本(SpringCloud的正式版是用伦敦地铁站或者说伦敦某地名的英文名称作为版本号,例如比较常用的F版本Finchley就是位于伦敦北部芬奇利)管理不同,SpringBoot的依赖组件发布版本格式是:X.Y.Z.RELEASE。因为SpringBoot组件一般会装箱为starter,所以组件的依赖GAV一般为:org.springframework.boot:spring-boot-starter-${组件名}:X.Y.Z.RELEASE,其中X是主版本,不同的主版本意味着可以放弃兼容性,也就是SpringBoot1.xSpringBoot2.x不保证兼容性,而组件名一般是代表一类中间件或者一类功能,如data-redisspring-boot-starter-data-redis,提供Redis访问功能)、jdbcspring-boot-starter-jdbc,提供基于JDBC驱动访问数据库功能)等等。以SpringBoot当前最新的发布版本2.3.1.RELEASEorg.springframework.boot:spring-boot-starter:jar:2.3.1.RELEASE为例,用mvn dependency:tree分析它的依赖关系如下:

这个依赖树也印证了starter是基于Spring项目装箱和扩展的。

SpringBoot依赖管理

如果使用Spring Initializr创建一个SpringBoot项目的话,那么会发现项目的POM文件中会加入了一个parent元素:

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

其实spring-boot-starter-parent相当于作为了当前项目的父模块,在父模块里面管理了当前指定的SpringBoot版本2.3.1.RELEASE所有依赖的第三方库的统一版本管理,通过spring-boot-starter-parent上溯到最顶层的项目,会找到一个properties元素,里面统一管理Spring框架和所有依赖到的第三方组件的统一版本号,这样就能确保对于一个确定的SpringBoot版本,它引入的其他starter不再需要指定版本,同时所有的第三方依赖的版本也是固定的。如项目的POM文件如下:

<!-- 暂时省略其他的配置属性 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

这样只需要修改parent元素中的版本号,就能全局更变所有starter的版本号。这种做法其实本质上是把当前项目作为spring-boot-starter-parent的子项目,其实在一定程度上并不灵活。这里推荐使用另一种方式:通过dependencyManagement元素全局管理SpringBoot版本,适用于单模块或者多模块的Maven项目。项目的(父)POM文件如下:

<!-- spring-boot-guide 父POM -->
<properties>
<spring.boot.version>2.3.1.RELEASE</spring.boot.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>

然后需要用到其他starter的时候,只需要在dependencies直接引入即可,不再需要指定版本号,版本号由dependencyManagement中定义的版本号统一管理。

<!-- spring-boot-guide/ch0-dependency 子POM -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>

SpringBoot依赖覆盖

有些特殊的情况,可能项目中大部分的starter使用的是相对低的版本,但是由于部分新的功能需要使用到更高版本的个别starter,则需要强制引入该高版本的starter。这里举一个例子,项目用到的SpringBoot组件的版本是2.1.5.RELEASE,使用的中间件服务Elasticsearch的版本是7.x,而spring-boot-starter-data-elasticsearch支持的版本如下:

理论上可以一下子升级SpringBoot2.3.1.RELEASE,其实也可以直接指定spring-boot-starter-data-elasticsearch的版本覆盖掉全局的SpringBoot组件版本,这里应用了Maven依赖调解原则

<!-- 父POM或者全局POM -->
<properties>
<spring.boot.version>2.1.5.RELEASE</spring.boot.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<version>2.3.1.RELEASE</version>
</dependency>
</dependencies>

这样就能单独提升spring-boot-starter-data-elasticsearch的版本为2.3.1.RELEASE,其他组件的版本依然保持为2.1.5.RELEASE

小结

目前有两种常用的方式管理SpringBoot组件的版本(两种方式二选一):

  1. 配置parent元素,通过项目继承的方式指定SpringBoot组件的版本号,这是Spring Initializr生成的项目中默认的配置方式。
  2. 配置dependencyManagement元素(推荐此方式),通过(父)POM文件统一指定SpringBoot组件的版本号。

另外,SpringBoot1.x2.x之间有兼容性问题(最明显的一点是2.x中删除了1.x中大量的内建类,如果用到了这些SpringBoot中的内建类,容易出现ClassNotFoundException),降级或者升级都有比较大的风险。一般情况下,建议使用同一个大版本进行项目开发,如果确定需要进行大版本切换,请务必做完毕的功能测试。

(本文完 c-1-d e-a-20200628)

SpringBoot2.x的依赖管理的更多相关文章

  1. SpringBoot原理深入及源码剖析(一) 依赖管理及自动配置

    前言 传统的Spring框架实现一个Web服务需要导入各种依赖jar包,然后编写对应的XML配置文件等,相较而言,SpringBoot显得更加方便.快捷和高效.那么,SpringBoot究竟是如何做到 ...

  2. 在Eclipse中使用建立使用Gradle做依赖管理的Spring Boot工程

    前述: Gradle存在很长时间了,以前只知道Maven和ivy ,最近才知道有这个存在,因为以后要用这个了; 所以,要先学会怎么用这个工具,就从建立一个简单工程开始! 实际上以前是见过Gradle的 ...

  3. Gradle Maven 依赖管理

    仓库管理简介 本质上说,仓库是一种存放依赖的容器,每一个项目都具备一个或多个仓库. Gradle支持以下仓库格式: Ivy仓库 Maven仓库 Flat directory仓库 我们来看一下,对于每一 ...

  4. webpack模块依赖管理介绍

    http://webpack.github.io/docs/ webpack is a module bundler. 是一个模块管理器 webpack可以管理模块的依赖关系,并产生可以替代这些模块的 ...

  5. Liferay7 BPM门户开发之43: Gradle依赖管理

    进入liferay v7.0,官方推荐使用Gradle进行依赖管理和发布,所以必须知道Gradle的用法,网上资料很多,不赘述 只写依赖管理的分类 一般用外部仓库依赖,也可以用本地文件依赖(依赖本地j ...

  6. Java Gradle入门指南之依赖管理(添加依赖、仓库、版本冲突)

        开发任何软件,如何管理依赖是一道绕不过去的坎,软件开发过程中,我们往往会使用这样那样的第三方库,这个时候,一个好的依赖管理就显得尤为重要了.作为一个自动构建工作,Gradle对依赖管理有着很好 ...

  7. 用CocoaPods做iOS程序的依赖管理(转摘)

    转摘自:http://blog.devtang.com/blog/2014/05/25/use-cocoapod-to-manage-ios-lib-dependency/ 文档更新说明 2012-1 ...

  8. mvc-6依赖管理

    CommonJS CommonJS规范,主要解决命名空间管理模块和用一套标准的编程模式来加载模块: 很快成为了JavaScript模块写法的事实标准: 它包含IO接口,底层的套接字流,以及单元测试等标 ...

  9. Composer : php依赖管理工具

    原始时代 我记得在当时用php的时候还没有composer,只有个pear,但是不好用呀,还不如直接在互联网上到处复制代码了,更快更不容易出错,当时也没有github这么好的社区工具了 总结如下 代码 ...

随机推荐

  1. MethodHandle(方法句柄)系列之三:invoke和invokeExact的区别

    先把代码贴上来,用的是一样的代码 /** * * @author LiuYeFeng<897908343@qq.com> * @date 2015年4月8日 下午10:41:13 * @C ...

  2. Java实现 LeetCode 674 最长连续递增序列(暴力)

    674. 最长连续递增序列 给定一个未经排序的整数数组,找到最长且连续的的递增序列. 示例 1: 输入: [1,3,5,4,7] 输出: 3 解释: 最长连续递增序列是 [1,3,5], 长度为3. ...

  3. 如何获取CSDN的积分?

    个人感觉就是写博客就给积分 具体给多少? CSDN应该有自己的积分规则 总之一句话:写博客涨积分

  4. Java实现 LeetCode 309 最佳买卖股票时机含冷冻期

    309. 最佳买卖股票时机含冷冻期 给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 .​ 设计一个算法计算出最大利润.在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股 ...

  5. Java实现 LeetCode 115 不同的子序列

    115. 不同的子序列 给定一个字符串 S 和一个字符串 T,计算在 S 的子序列中 T 出现的个数. 一个字符串的一个子序列是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字 ...

  6. Java实现LeetCode 110. Balanced Binary Tree

    /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * Tre ...

  7. Java实现LeetCode_0026_RemoveDuplicatesFromSortedArray

    package javaLeetCode.primary; public class RemoveDuplicatesFromSortedArray_26 { public static void m ...

  8. 性能测试中TPS上不去的原因

    TPS(Transaction Per Second):每秒事务数,指服务器在单位时间内(秒)可以处理的事务数量,一般以request/second为单位. 压测中为什么TPS上不去的原因: .网络带 ...

  9. 一文了解Docker容器技术的操作

    一文了解Docker容器技术的操作 前言一.Docker是什么二.Docker的安装及测试Docker的安装Docker的Hello world测试三.Docker的常见操作镜像的基本操作容器的基本操 ...

  10. 你是项目经理了![IT项目经理成长晋升记1]

    凉爽的秋风,吹走了严热的夏季,K公司内部传来一个重磅消息.销售团队披荆斩棘,过三关斩六将,成功胜出,拿下公司在C省的首单,为C省市场的开拓打下了基础. K公司是2003年“非典”时期成立,坐落在美丽的 ...