SpringBoot-start机制

发布时间 2023-05-08 10:28:25作者: leepandar

SpringBoot-start机制

start机制

传统的Spring项目开发,需要导入大量的依赖,同时还需要对各种XML配置文件进行配置,过程十分繁琐。而Spring Boot项目创建完成后,即使不编写任何代码,不用进行任何配置也能运行。这些都要归功于Spring Boot的Start机制。

在没有 starter 之前,假如我想要在 Spring 中使用 jpa,那我可能需要做以下操作:

  • 在 Maven 中引入使用的数据库的依赖(即 JDBC 的 jar)
  • 引入 jpa 的依赖
  • 在 xxx.xml 中配置一些属性信息
  • 反复的调试直到可以正常运行

Starters是一个依赖描述符的集合,你可以将它包含进项目中,这样添加依赖就非常方便。你可以获取所有Spring及相关技术的一站式服务,而不需要翻阅示例代码,拷贝粘贴大量的依赖描述符。例如,如果你想使用Spring和JPA进行数据库访问,只需要在项目中包含spring-boot-starter-data-jpa依赖,然后你就可以开始了。

该starters包含很多搭建,快速运行项目所需的依赖,并提供一致的,可管理传递性的依赖集。

名字有什么含义:所有官方starters遵循相似的命名模式:spring-boot-starter-*,在这里*是一种特殊的应用程序类型。该命名结构旨在帮你找到需要的starter。很多集成于IDEs中的Maven插件允许你通过名称name搜索依赖。例如,使用相应的Eclipse或STS插件,你可以简单地在POM编辑器中点击ctrl-space,然后输入"spring-boot-starter"就可以获取一个完整列表。第三方starters不应该以spring-boot开头,因为它跟Spring Boot官方artifacts冲突。一个acme的第三方starter通常命名为acme-spring-boot-starter

Spring Boot 将日常企业应用研发中的各种场景都抽取出来,做成一个个的 starter(启动器),starter 中整合了该场景下各种可能用到的依赖,用户只需要在 Maven 中引入 starter 依赖,Spring Boot 就能自动扫描到要加载的信息并启动相应的默认配置。starter 提供了大量的自动配置,让用户摆脱了处理各种依赖和配置的困扰。所有这些 starter 都遵循着约定成俗的默认配置,并允许用户调整这些配置,即遵循“约定大于配置”的原则。 所谓的“约定大于配置”,对于Spring Boot来说:

  • 开发人员仅需规定应用中不符合约定的部分
  • 在没有规定配置的地方,采用默认配置,以力求最简配置为核心思想

整体逻辑

image

spring-boot-starter-web

以 spring-boot-starter-web 为例,它能够为提供 Web 开发场景所需要的几乎所有依赖,因此在使用 Spring Boot 开发 Web 项目时,只需要引入该 Starter 即可,而不需要额外导入 Web 服务器和其他的 Web 依赖。通过IDEA可以看到其对应导入的依赖:

      <!--Spring Boot所需Jar包-->
      <parent>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-parent</artifactId>
          <version>2.4.5</version>
          <relativePath/>
      </parent>
   
      <dependencies>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
   
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-test</artifactId>
              <scope>test</scope>
          </dependency>
      </dependencies>

从以上结果中,我们可以看到 Spring Boot 导入了 springframework、logging、jackson 以及 Tomcat 等依赖,而这些正是我们在开发 Web 项目时所需要的。

spring-boot-starter-parent

在以上 pom.xml 的配置中,引入依赖 spring-boot-starter-web 时,并没有指明其版本(version),但在依赖树中,我们却看到所有的依赖都具有版本信息,那么这些版本信息是在哪里控制的呢?其实,这些版本信息是由 spring-boot-starter-parent(版本仲裁中心) 统一控制的。

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.5</version>
        <relativePath/>
    </parent>

Spring Boot 项目可以通过继承 spring-boot-starter-parent 来获得一些合理的默认配置,它主要提供了以下特性:

  • 默认 JDK 版本(Java 8)
  • 默认字符集(UTF-8)
  • 依赖管理功能
  • 资源过滤
  • 默认插件配置
  • 识别 application.properties 和 application.yml 类型的配置文件

查看 spring-boot-starter-parent 的底层代码,可以发现其有一个父级依赖 spring-boot-dependencies

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.4.5</version>
</parent>

spring-boot-dependencies 的底层代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.4.5</version>
    <packaging>pom</packaging>
    ....
    <properties>
        <activemq.version>5.16.1</activemq.version>
        <antlr2.version>2.7.7</antlr2.version>
        <appengine-sdk.version>1.9.88</appengine-sdk.version>
        <artemis.version>2.15.0</artemis.version>
        <aspectj.version>1.9.6</aspectj.version>
        <assertj.version>3.18.1</assertj.version>
        <atomikos.version>4.0.6</atomikos.version>
        ....
    </properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.apache.activemq</groupId>
                <artifactId>activemq-amqp</artifactId>
                <version>${activemq.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.activemq</groupId>
                <artifactId>activemq-blueprint</artifactId>
                <version>${activemq.version}</version>
            </dependency>
            ...
        </dependencies>
    </dependencyManagement>
    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>build-helper-maven-plugin</artifactId>
                    <version>${build-helper-maven-plugin.version}</version>
                </plugin>
                <plugin>
                    <groupId>org.flywaydb</groupId>
                    <artifactId>flyway-maven-plugin</artifactId>
                    <version>${flyway.version}</version>
                </plugin>
                ...
            </plugins>
        </pluginManagement>
    </build>
</project>

以上配置中,部分元素说明如下:

  • dependencyManagement :负责管理依赖;
  • pluginManagement:负责管理插件;
  • properties:负责定义依赖或插件的版本号。

spring-boot-dependencies 通过 dependencyManagementpluginManagementproperties 等元素对一些常用技术框架的依赖或插件进行了统一版本管理,例如 ActivemqSpringTomcat 等。