学透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.

相关推荐
LuckyLay5 分钟前
Spring学习笔记_27——@EnableLoadTimeWeaving
java·spring boot·spring
向阳121818 分钟前
Dubbo负载均衡
java·运维·负载均衡·dubbo
Gu Gu Study28 分钟前
【用Java学习数据结构系列】泛型上界与通配符上界
java·开发语言
WaaTong1 小时前
《重学Java设计模式》之 原型模式
java·设计模式·原型模式
m0_743048441 小时前
初识Java EE和Spring Boot
java·java-ee
AskHarries1 小时前
Java字节码增强库ByteBuddy
java·后端
佳佳_1 小时前
Spring Boot 应用启动时打印配置类信息
spring boot·后端
小灰灰__1 小时前
IDEA加载通义灵码插件及使用指南
java·ide·intellij-idea
夜雨翦春韭1 小时前
Java中的动态代理
java·开发语言·aop·动态代理
程序媛小果2 小时前
基于java+SpringBoot+Vue的宠物咖啡馆平台设计与实现
java·vue.js·spring boot