spring-boot-starter-parent 项目的作用

前言

当我们使用 Spring Initializr 创建 Spring Boot 项目时,发现总会继承一个 spring-boot-starter-parent 作用父类。假如不继承就不能用了吗?这个父类的作用是什么呢?
springboot demo
在深入探究之前我们需要先了解一下 Maven 的继承特性。

Maven 继承

Maven 在设计时,借鉴了 Java 面向对象思想,提出了 POM 继承的概念。当一个项目中包含多个子模块时,可以在子模块的 POM 中通过 <parent/> 标签指明其父项目,同时在父模块(项目)中通过 <modules/> 指定它包含哪些子模块。这样就确定不同模块之间的继承关系。其带来的好处是,只需要在父模块中指定依赖模块的版本,子模块不用关心,方便统一管理,减少不同模块相同依赖项版本相互冲突的问题。需要指明的是,如果一个模块定义为父模块,则其 <pakaging/> 属性必须为 pom。

spring-boot-starter-parent

回答上面的问题:如果不继承 spring-boot-starter-parent 就不能使用 Springboot 项目了吗?

答案肯定是否定的。如果我们打开 spring-boot-starter-parent 项目的 POM 文件就会发现,其实它又继承了另外一个 POM,而它本身只引入了 spring-boot-starter 一个依赖项(如果在 initializr的时候没有选择其它依赖项),另外还指定了 java 版本和两个 compiler 插件。

完整的 spring-boot-starter-parent 项目POM文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.0.5.RELEASE</version>
    <relativePath>../spring-boot-dependencies</relativePath>
  </parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-parent</artifactId>
  <version>2.0.5.RELEASE</version>
  <packaging>pom</packaging>
  <name>Spring Boot Parent</name>
  <description>Spring Boot Parent</description>
  <url>https://projects.spring.io/spring-boot/#/spring-boot-parent</url>
  <organization>
    <name>Pivotal Software, Inc.</name>
    <url>https://spring.io</url>
  </organization>
  <licenses>
    <license>
      <name>Apache License, Version 2.0</name>
      <url>http://www.apache.org/licenses/LICENSE-2.0</url>
    </license>
  </licenses>
  <developers>
    <developer>
      <name>Pivotal</name>
      <email>info@pivotal.io</email>
      <organization>Pivotal Software, Inc.</organization>
      <organizationUrl>http://www.spring.io</organizationUrl>
    </developer>
  </developers>
  <prerequisites>
    <maven>3.5</maven>
  </prerequisites>
  <scm>
    <connection>scm:git:git://github.com/spring-projects/spring-boot.git</connection>
    <developerConnection>scm:git:ssh://git@github.com/spring-projects/spring-boot.git</developerConnection>
    <url>http://github.com/spring-projects/spring-boot</url>
  </scm>
  <issueManagement>
    <system>Github</system>
    <url>https://github.com/spring-projects/spring-boot/issues</url>
  </issueManagement>
</project>

会发现它其实继承了 spring-boot-dependencies 。

spring-boot-dependencies

既然 sprin-boot-starter-parent 继承了 dependencies,那么 dependencies 里又做了些什么呢?因为 dependencies 的 POM 文件内容太长就不在这里列出了。其主要内容就是 <dependencyManagement/> 和 <pluginManagement/> 两个标签。

可以这么说:dependencies 通过 <DependencyManagement/> 和 <pluginManagement/> 两个标签统一指定了很多依赖并明确了它们的版本号,实现了上面我们说的统一版本管理,但其实并未真的引入这些依赖项。

dependencyManagement 和 pluginManagement

Maven 通过这种 xxxManagement 标签,或者说组件对依赖进行管理,它具有以下2大特性:

  • 在该元素下声明的依赖不会实际引入到模块中,只有在 dependencies 元素下同样声明了该依赖,才会引入到模块中。
  • 该元素能够约束 dependencies 下依赖的使用,即 dependencies 声明的依赖若未指定版本,则使用 dependencyManagement 中指定的版本,否则将覆盖 dependencyManagement 中的版本。

综上,spring-boot-dependencies 项目,或者说 spring-boot-starter-parent 项目只是给我们提供了一个管理依赖的 POM,而这些依赖是在当前 springboot 版本下进行验证过的一个依赖合集。

如果不引入(继承)spring-boot-starter-parent

我们新建一个空的 Maven 项目,依赖中引入 spring-boot-starter 框架(注意指定 version),然后在启动类上加上@SpringBootApplication 注解,照样可以成功启动:
不引入spring-boot-starter-parent

Maven单继承问题

有人可能会问,如果我想使用 spring-boot-starter-parent 提供的依赖管理,但又不想继承它,可不可以?

答案是肯定的。

单继承:maven和Java一样都是单继承机制,maven当中有 <type>pom</type> 和 <scope>import</scope> ,通过这两个标签在dependencyManagement中声明依赖,可以替代继承(达到类似parent标签的作用,解决了单继承问题)。

<dependencyManagement>
	<dependencies>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-dependencies</artifactId>
           <version>3.4.3</version>
           <type>pom</type>
           <scope>import</scope>
       </dependency>
   </dependencies>
</dependencyManagement>

注意上面是官方推荐的方式,即引入 spring-boot-dependencies,而不是 spring-boot-starter-parent。但这样并不等价于继承 parent 的方式,原因是 import 依赖范围只能与 dependencyManagement 元素配合使用才会有效,其功能是将目标 pom.xml 中的 dependencyManagement 配置导入合并到当前 pom.xml 的 dependencyManagement 中,所以这种方式并没有把 parent 中引用的 plugin 一并继承过来,所以还需要我们自己声明打包插件的引用:

<build>
	<plugings>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
			<version>3.8.1</version>
		</plugin>
	</plugins>
</build>
posted @ 2025-03-10 19:18  凉皮也是菜  阅读(31)  评论(0)    收藏  举报  来源