学透Spring Boot — 005. 深入理解 Spring Boot Starter 依赖管理

前面的文章直观的展示了,使用Spring Boot 集成 Hibernate 和手动集成 Hibernate 之间差距。

一个比喻

工作中使用过Spring Boot一段时间后,我越来越感觉到Spring Boot Starter带来的便利性。

使用手动集成 Hibernate , 就像去电脑城配电脑:

  • 你不仅要找齐所有必备的部件,比如CPU、内存、主板、显卡等等:
  • 你还要保证各个零部件是相互兼容的,比如太老的主板不支持某些显卡等等
    这样导致,组装电脑的成本很大,费时费力!这和我们开发中手动集成某个模块非常类似。

但是如果使用 Spring Boot Starter,就像我们买电脑时,直接买笔记本电脑或者一体机。

用一个词形容就是 开箱即用。

Starter的依赖管理

Spring Boot Starter 是Spring Boot 中非常重要的概念,它是一种提供依赖项的方式,可以帮助开发人员快速集成各种第三方库和框架。

它应该包含两方面的内容:

  1. 依赖管理
  2. 自动配置

今天我们主要讨论的是其中的 依赖管理 部分。

前面博文说到,只要在在pom.xml中加一个依赖项,我们就几乎把持久层的所有依赖都自动加到我们的项目了(当然你还需要加数据库驱动):

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

但是这是怎么做到的呢?今天我们就来一探究竟。

什么是 Maven POM

pom.xml 这个我们经常打交道的文件,今天我们来深入学习它。

POM ( Project Object Model,项目对象模型 ) 是 Maven 工程的基本工作单元,是一个XML文件,包含了项目的基本信息,用于描述项目如何构建,声明项目依赖,等等。

POM 中做很多很多事,这些事都是和项目构建相关的,比如:

  • 声明和管理项目依赖
  • 配置各种插件
  • 执行目标
  • 项目构建 profile
  • 指定项目版本

当然我们最最常用的是声明和管理项目用到的各种依赖。

它的主要结构如下:

xml 复制代码
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.companyname.project-group</groupId>
    <artifactId>project</artifactId>
    <version>1.0</version>
    
    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
    </dependencies>
</project>

这里只是列出了最核心的元素,也是和我们本文相关的。
pom.xml 文件详解请看这里

其中的 <dependencies> 是我们重点关注的对象,它定义了项目相关的所有依赖。

这些依赖组成了项目构建过程中的一个个环节。它们自动从项目定义的仓库中下载(比如你配置了阿里云仓库,或者默认的maven中央仓库)。

什么是 Maven 依赖传递

想象一下,在很久很久以前,在没有Maven等构建工具时,我们要手动下载三方jar包,然后放到我们的项目的lib目录下。

如果这些三方的jar包是这种依赖关系时。

  • 如果我们的项目用到了A包,那么我们需要手动下载A、B、C、D、E包到lib目录
  • 如果我们项目用到了B包,那么我们需要手动下载B、C、E包到lib目录下
  • ......

    好在,Maven 引入了一个依赖传递传递机制,帮我们大大简化了这个问题。

有了这个机制,当我们项目中用到A.jar时,我们只需要在pom.xml的声明A,至于它依赖的其它jar包,都会被自动的依赖进来,包括它依赖的依赖。

当然传递依赖会引发一些问题,关于排除依赖等不在本文的范围。

Spring Boot Starter的依赖

通过学习上面的知识,我们就很容易理解为什么声明一个依赖,就会自动把所有的持久层依赖都自动加入进来了。

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

平时我们声明其它依赖时,都需要指定版本,但是为什么可以不指定?因为默认不指定时,它会根据项目的父级依赖管理来确定依赖项的版本。

我们在pom.xml的上面部分可以看到父级项目

xml 复制代码
<parent>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-parent</artifactId>
     <version>3.2.4</version>
     <relativePath/> <!-- lookup parent from repository -->
 </parent>

可以看到父级项目版本是3.2.4, 所以相当于:

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <version>3.2.4</version>
</dependency>

这个依赖我们可以按住ctrl键 加鼠标左键,可以跳转到它的pom.xml中去

这个pom.xml文件在你的本地的maven 仓库的某个目录下,比如:

这个包和普通我们依赖的包看上去并没有没什么区别。

要说最大的区别,就是它虽然是一个jar,但是并不包含java代码,在IDEA的依赖中可以看到,里面只有一些声明文件

这是因为,这个jar存在的唯一意义,就是定义一组依赖。

所以我们重点看 spring-boot-starter-data-jpa-3.2.4.pom 文件的 dependencies:

xml 复制代码
<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
    <version>3.2.4</version>
    <scope>compile</scope>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
    <version>3.2.4</version>
    <scope>compile</scope>
  </dependency>
  <dependency>
    <groupId>org.hibernate.orm</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>6.4.4.Final</version>
    <scope>compile</scope>
  </dependency>
  <dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-jpa</artifactId>
    <version>3.2.4</version>
    <scope>compile</scope>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>6.1.5</version>
    <scope>compile</scope>
  </dependency>
</dependencies>

可以看到,它依赖5个包:

  • spring-boot-starter-aop
  • spring-boot-starter-jdbc
  • hibernate-core
  • spring-data-jpa
  • spring-aspects

这五个包,前面两个也是 starter,后面3个是普通的包。

然后这些依赖又会递归的把它们的依赖包含进来。

最终的依赖图

根据pom.xml中的依赖传递,我们可以得到一个依赖关系图

是不是非常眼熟呢?对的,就是我们前文中贴出来的IDEA生成的依赖:

Spring Boot 做了什么

前面可以看到,定义一个spring-boot-starter-data-jpa 依赖就把我们持久层的所有依赖都搞定,其实是 maven 做到的,确切的说是maven的依赖传递机制完成的,并不是Spring Boot的新特性。

那么Spring Boot在这里做了什么呢?

其实它主要的是任务是打包,它按一般的场景划分成多个模块,然后定义每个模块下的一组依赖。就比如前面的 spring-boot-starter-data-jpa-3.2.4 它定义了:

  • spring-boot-starter-aop-3.2.4
  • spring-boot-starter-jdbc-3.2.4
  • hibernate-core-6.4.4.Final
  • spring-data-jpa-3.2.4
  • spring-aspects-6.1.5

它不仅指示某个模块下,哪些依赖是必须的;
还指定了依赖具体的版本号。

这些版本的依赖都是经 Spring Boot 官方测试过的,我们可以放心的使用。

Spring Boot 官方提供的Starter

Spring Boot 官方提供了几十个开箱即用的Starter,几乎涵盖了所有项目常见的场景。

有了这些starter,你再也不用到处找演示文档了,不用再一个个配置必备的依赖了,也不用担心版本兼容问题。使用某个模块,直接使用这个模块的starter即可。

我们可以把这些starter 理解成套餐,大部分项目都会这么用spring-web, 这么用redis等等,Spring Boot已经帮我们打包好了,你直接享用即可。

1. 应用相关的Starter
Name Description
spring-boot-starter Core starter, including auto-configuration support, logging and YAML
spring-boot-starter-activemq Starter for JMS messaging using Apache ActiveMQ
spring-boot-starter-amqp Starter for using Spring AMQP and Rabbit MQ
spring-boot-starter-aop Starter for aspect-oriented programming with Spring AOP and AspectJ
spring-boot-starter-artemis Starter for JMS messaging using Apache Artemis
spring-boot-starter-batch Starter for using Spring Batch
spring-boot-starter-cache Starter for using Spring Framework's caching support
spring-boot-starter-data-cassandra Starter for using Cassandra distributed database and Spring Data Cassandra
spring-boot-starter-data-cassandra-reactive Starter for using Cassandra distributed database and Spring Data Cassandra Reactive
spring-boot-starter-data-couchbase Starter for using Couchbase document-oriented database and Spring Data Couchbase
spring-boot-starter-data-couchbase-reactive Starter for using Couchbase document-oriented database and Spring Data Couchbase Reactive
spring-boot-starter-data-elasticsearch Starter for using Elasticsearch search and analytics engine and Spring Data Elasticsearch
spring-boot-starter-data-jdbc Starter for using Spring Data JDBC
spring-boot-starter-data-jpa Starter for using Spring Data JPA with Hibernate
spring-boot-starter-data-ldap Starter for using Spring Data LDAP
spring-boot-starter-data-mongodb Starter for using MongoDB document-oriented database and Spring Data MongoDB
spring-boot-starter-data-mongodb-reactive Starter for using MongoDB document-oriented database and Spring Data MongoDB Reactive
spring-boot-starter-data-neo4j Starter for using Neo4j graph database and Spring Data Neo4j
spring-boot-starter-data-r2dbc Starter for using Spring Data R2DBC
spring-boot-starter-data-redis Starter for using Redis key-value data store with Spring Data Redis and the Lettuce client
spring-boot-starter-data-redis-reactive Starter for using Redis key-value data store with Spring Data Redis reactive and the Lettuce client
spring-boot-starter-data-rest Starter for exposing Spring Data repositories over REST using Spring Data REST and Spring MVC
spring-boot-starter-freemarker Starter for building MVC web applications using FreeMarker views
spring-boot-starter-graphql Starter for building GraphQL applications with Spring GraphQL
spring-boot-starter-groovy-templates Starter for building MVC web applications using Groovy Templates views
spring-boot-starter-hateoas Starter for building hypermedia-based RESTful web application with Spring MVC and Spring HATEOAS
spring-boot-starter-integration Starter for using Spring Integration
spring-boot-starter-jdbc Starter for using JDBC with the HikariCP connection pool
spring-boot-starter-jersey Starter for building RESTful web applications using JAX-RS and Jersey. An alternative to spring-boot-starter-web
spring-boot-starter-jooq Starter for using jOOQ to access SQL databases with JDBC. An alternative to spring-boot-starter-data-jpa or spring-boot-starter-jdbc
spring-boot-starter-json Starter for reading and writing json
spring-boot-starter-mail Starter for using Java Mail and Spring Framework's email sending support
spring-boot-starter-mustache Starter for building web applications using Mustache views
spring-boot-starter-oauth2-authorization-server Starter for using Spring Authorization Server features
spring-boot-starter-oauth2-client Starter for using Spring Security's OAuth2/OpenID Connect client features
spring-boot-starter-oauth2-resource-server Starter for using Spring Security's OAuth2 resource server features
spring-boot-starter-pulsar Starter for using Spring for Apache Pulsar
spring-boot-starter-pulsar-reactive Starter for using Spring for Apache Pulsar Reactive
spring-boot-starter-quartz Starter for using the Quartz scheduler
spring-boot-starter-rsocket Starter for building RSocket clients and servers
spring-boot-starter-security Starter for using Spring Security
spring-boot-starter-test Starter for testing Spring Boot applications with libraries including JUnit Jupiter, Hamcrest and Mockito
spring-boot-starter-thymeleaf Starter for building MVC web applications using Thymeleaf views
spring-boot-starter-validation Starter for using Java Bean Validation with Hibernate Validator
spring-boot-starter-web Starter for building web, including RESTful, applications using Spring MVC. Uses Tomcat as the default embedded container
spring-boot-starter-web-services Starter for using Spring Web Services
spring-boot-starter-webflux Starter for building WebFlux applications using Spring Framework's Reactive Web support
spring-boot-starter-websocket Starter for building WebSocket applications using Spring Framework's MVC WebSocket support
2. 生产相关的starter
Name Description
spring-boot-starter-actuator Starter for using Spring Boot's Actuator which provides production-ready features to help you monitor and manage your application
3. 技术相关的starter
Name Description
spring-boot-starter-jetty Starter for using Jetty as the embedded servlet container. An alternative to spring-boot-starter-tomcat
spring-boot-starter-log4j2 Starter for using Log4j2 for logging. An alternative to spring-boot-starter-logging
spring-boot-starter-logging Starter for logging using Logback. Default logging starter
spring-boot-starter-reactor-netty Starter for using Reactor Netty as the embedded reactive HTTP server.
spring-boot-starter-tomcat Starter for using Tomcat as the embedded servlet container. Default servlet container starter used by spring-boot-starter-web
spring-boot-starter-undertow Starter for using Undertow as the embedded servlet container. An alternative to spring-boot-starter-tomcat

总结

通过本文,我们深入学习了 Spring Boot Starter 依赖管理背后的 Maven的传递依赖机制是如何工作的,以及 Spring Boot 提供了哪些开箱即用的starter。

这是Spring Boot 系列专栏的第5篇,下一篇我们将深入学习Spring Boot的自动配置,关注我,和我一起学透 Spring Boot.

相关推荐
林树的编程频道6 小时前
快递的物流地图是怎么实现的
后端
洛小豆6 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
八怪6 小时前
联合索引使用高分区度字段的一个例子
后端
IT_陈寒6 小时前
JavaScript 性能优化:5 个被低估的 V8 引擎技巧让你的代码快 200%
前端·人工智能·后端
前端小张同学6 小时前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole6 小时前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端
华仔啊6 小时前
基于 RuoYi-Vue 轻松实现单用户登录功能,亲测有效
java·vue.js·后端
bobz9656 小时前
ebpf 应用于 qemu vm vTAP
后端
bobz9657 小时前
ebpf 直接为虚拟机 tap 网卡提供 零 copy
后端