1. 程式人生 > >【spring-boot 原始碼解析】spring-boot 依賴管理

【spring-boot 原始碼解析】spring-boot 依賴管理

關鍵詞:spring-boot 依賴管理、spring-boot-dependencies、spring-boot-parent

問題

maven 工程,依賴管理是非常基本又非常重要的功能,現在的工程越來越龐大,依賴越來越多,各種二方包、三方包太多太多,依賴衝突處理起來真是讓人頭疼,經常需要涉及到多個地方需要調整。

微信公眾號:逸飛兮(專注於java知識領域的原始碼分析,從原始碼中理解框架/工具原理、驗證CS專業知識)

解決方案

使用統一的依賴管理模組來管理工程中的所有依賴。

spring-boot 工程常使用 spring-boot-dependencies、spring-boot-starter-parent 管理工程依賴。

spring-boot 的最上級工程是 spring-boot-build,以下開始一步一步深入瞭解 spring-boot 依賴解決方案。

spring-boot 中的方案

spring-boot-build

spring-boot 的最上層工程,指定了 maven profiles、maven repositories、maven pluginRepositories、maven build pluginManagement。

  • profiles:中包含程式碼風格檢查、程式碼風格 format;更方便匯入 eclipse;maven 倉庫
  • repositories:允許在開發過程中匯入快照和里程碑 BOM。這個部分在 install/deploy 期間被 flatten 外掛刪除。包含 maven 中央倉庫、spring 快照倉庫、spring 里程碑倉庫
  • pluginRepositories:外掛倉庫,包含 maven 中央倉庫、spring 快照倉庫、spring 里程碑倉庫
  • pluginManagement:構建外掛管理,這個外掛的配置只用於儲存 Eclipse m2e 設定,它對 Maven 構建本身沒有影響。

spring-boot-dependencies

dependencies 的父工程是spring-boot-build,不包含程式碼,只用 pom 來管理依賴,pom.xml 如下:

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-build</artifactId>
        <version>${revision}</version>
        <relativePath>../..</relativePath>
</parent>
<artifactId>spring-boot-dependencies</artifactId>
<packaging>pom</packaging>
<dependencyManagement>
  <!-- 省略具體依賴管理 -->
</dependencyManagement>
<build>
  <pluginManagement>
    <!-- 省略具體構建外掛管理 -->
  </pluginManagement>
  <plugins>
    <!-- 省略具體構建外掛 -->
  </plugins>
</build>

從 pom 中可以看出,spring-boot-dependencies 中除了引入了(3 個)外掛,更多的是做版本的管理。

其中,引入的外掛是:

  • flatten-maven-plugin:對 pom 精簡外掛
  • xml-maven-plugin:1. 根據 schema 驗證 XML 檔案;2. 使用 XSLT 樣式轉換 XML 檔案
  • build-helper-maven-plugin:指定多個原始碼目錄

dependencyManagement 中差不多管理了 spring-boot 工程中所有的依賴。

pluginManagement 中管理了常用的各種 maven 外掛,這裡就不詳述了。

其中包含了 maven-clean-plugin、maven-compiler-plugin、maven-assembly-plugin、maven-war-plugin、maven-jar-plugin、spring-boot-maven-plugin,其中 spring-boot-maven-plugin 外掛對於 spring-boot 工程非常重要,會把 maven 打包成的 jar 重新打包成可執行 jar。

spring-boot-starter-parent(重要)

既然有了 spring-boot-dependencies 這麼豐富的依賴、外掛版本管理,那麼還搞一個 spring-boot-starter-parent 呢?

spring-boot-starter-parent 的父工程是spring-boot-dependencies,不包含程式碼,只用 pom 來管理依賴,pom.xml 如下:

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-dependencies</artifactId>
  <version>${revision}</version>
  <relativePath>../../spring-boot-dependencies</relativePath>
</parent>
<artifactId>spring-boot-starter-parent</artifactId>
<packaging>pom</packaging>
<name>Spring Boot Starter Parent</name>
<description>Parent pom providing dependency and plugin management for applications
  built with Maven</description>
<properties>
  <main.basedir>${basedir}/../../..</main.basedir>
  <java.version>1.8</java.version>
  <!-- 資源分隔符 -->
  <resource.delimiter>@</resource.delimiter> <!-- delimiter that doesn't clash with Spring ${} placeholders -->
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  <maven.compiler.source>${java.version}</maven.compiler.source>
  <maven.compiler.target>${java.version}</maven.compiler.target>
</properties>
<build>
  <resources>
    <resource>
      <directory>${basedir}/src/main/resources</directory>
      <filtering>true</filtering>
      <includes>
        <include>**/application*.yml</include>
        <include>**/application*.yaml</include>
        <include>**/application*.properties</include>
      </includes>
    </resource>
    <resource>
      <directory>${basedir}/src/main/resources</directory>
      <excludes>
        <exclude>**/application*.yml</exclude>
        <exclude>**/application*.yaml</exclude>
        <exclude>**/application*.properties</exclude>
      </excludes>
    </resource>
  </resources>
  <pluginManagement>
    <plugins>
      <!-- 省略其它不用太關心的 plugin -->
      <!-- spring-boot 提供的 maven 重打包外掛,重要!!! -->
      <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <executions>
              <execution>
                <id>repackage</id>
                <goals>
                  <goal>repackage</goal>
                </goals>
              </execution>
            </executions>
            <configuration>
              <mainClass>${start-class}</mainClass>
            </configuration>
          </plugin>
    </plugins>
  </pluginManagement>
  <plugins>
            <!-- 引入公共外掛:flatten-maven-plugin、xml-maven-plugin -->
  </plugins>

特性

  • 預設編譯版本:Java 1.8
  • 原始碼編碼:UTF-8
  • 繼承自 spring-boot-dependencies 的 dependencyManagement
  • spring-boot-maven-plugin 的 goal 設定為 repackage
  • maven 資源過濾(application*.yml、application*.yaml、application*.properties 等)、外掛配置
  • 資源分隔符:“@”,在 application*.yml 中使用@來引用 maven 屬性,常見用法如下:spring.application.name=@artifactId@

Note that, since the application.properties and application.yml files accept Spring style placeholders (${…}), the Maven filtering is changed to use @..@placeholders. (You can override that by setting a Maven property called resource.delimiter.)

譯:

注意,由於 application.properties 和 application.yml 檔案接受 spring 樣式的佔位符($…),所以 maven filter 將更改為使用@…@佔位符。(可以通過設定名為 resource.delimiter 的 maven 屬性來覆蓋該屬性。)

spring-boot-parent

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>${revision}</version>
        <relativePath>../spring-boot-dependencies</relativePath>
</parent>
<artifactId>spring-boot-parent</artifactId>
<packaging>pom</packaging>
<dependencyManagement>
  <!-- 省略具體依賴管理 -->
</dependencyManagement>
<dependencies>
  <!-- 省略具體依賴 -->
</dependencies>
<build>
  <pluginManagement>
    <!-- 省略具體構建外掛管理 -->
  </pluginManagement>
  <plugins>
    <!-- 省略具體構建外掛 -->
  </plugins>
  <profiles>
    <!-- 省略具體 profile -->
  </profiles>
</build>

dependencyManagement

包含兩個部分:

  • 內部未釋出的 spring-boot 依賴
  • 附加的 Spring 引導依賴項 (對使用者無效)

因此,這裡所加入的依賴管理,使用者不需要關心,很好,省心。

dependencies

公共的依賴,主要是一些測試依賴,如:junit、hamcrest、mockito、spring-test,還有斷言依賴:assertj。

plugins

添加了 spring-boot 公用的一些外掛,如:maven-compiler-plugin、maven-jar-plugin、maven-war-plugin、maven-source-plugin 等

profiles

使用者基本不用關心。省略

選擇

spring-boot-dependencies 和 spring-boot-starter-parent、 spring-boot-parent 都提供了依賴管理的功能,那我們在開發的過程中,到底使用哪個呢?

  • spring-boot-parent :目的不是提供給使用者使用的,使用 spring-boot 開源專案用於管理 spring-boot-project 整個大工程中的除了 spring-boot-starters (提供給我們使用的各個開箱即用的三方包) 的其他模組的。
  • spring-boot-starter-parent:我們通過 Spring Initializr 構建一個 spring-boot 專案的時候,官方預設是讓我們使用的 spring-boot-starter-parent ,大致可以認為官方建議使用此方式管理依賴,畢竟此方式提供的依賴、外掛管理更多,更適合使用。
  • spring-boot-dependencies:若在使用的時候,工程不想指定父工程,或者必須使用公司的父工程,可以通過 dependencyManagement 引入此依賴管理。

使用 spring-boot-dependencies,相比較 spring-boot-starter-parent 的時候特別注意要加上spring-boot-maven-plugin,如下:

<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
  </plugins>
  <pluginManagement>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <version>${springboot.version}</version>
      </plugin>
    </plugins>
  </pluginManagement>
</build>

至於 spring-boot-starter-parent 的其他額外指定的 jar,按需新增。

實際使用

在工程中使用的時候,所有的二方、三方 jar 都應該統一管理,除了 spring-boot 提供的依賴,我們還有很多 jar 需要管理,如:mysql 驅動包、mybatis 包、各種工具包或者公司內的二方包等。因此,最好使用一個單獨的模組來構建自己的 dependencies 或 parent。

待續

em……寫到這裡就結束了嗎?似乎還沒有,還需要細緻分析下一些具體依賴是如何選擇的,比如:spring-boot 選擇的是什麼日誌框架,logback?log4j2?log4j?那對於程式碼中不是用 spring-boot 指定的日誌實現時,spring-boot 又是怎麼做的呢?期待後續更新?更或者不更新,誰知道呢?

專注於java知識領域的原始碼分析,從原始碼中理解框架/工具原理、驗證CS專業知識的應用

相關推薦

spring-boot 原始碼解析spring-boot 依賴管理

關鍵詞:spring-boot 依賴管理、spring-boot-dependencies、spring-boot-parent 問題 maven 工程,依賴管理是非常基本又非常重要的功能,現在的工程越來越龐大,依賴越來越多,各種二方包、三方包太多太多,依賴衝突處理起來真是讓人頭疼,經常需要涉及到多個地方需要

spring-boot 原始碼解析spring-boot 依賴管理梳理圖

在文章 【spring-boot 原始碼解析】spring-boot 依賴管理 中,我梳理了 spring-boot-build、spring-boot-parent、spring-boot-dependencies、spring-boot-starter-parent 依賴之間的關係,以及我們平常應該怎麼用

cocos2d-x 原始碼解析幀動畫

前言 幀動畫是以序列幀輪放的方式來表現一個動畫,就像膠片電影一樣,一張張畫面進行切換,當切換的間隔足夠小時,人眼就看不出中間的間隔,而是一個流暢的視訊。cocos2d-x 中的幀動畫涉及到三個類 AnimationFrame,Animation 和 Anima

原始碼解析憑什麼?spring boot 一個 jar 就能開發 web 專案

問題 為什麼開發web專案,spring-boot-starter-web 一個jar就搞定了?這個jar做了什麼? 通過 spring-boot 工程可以看到所有開箱即用的的引導模組 spring-boot-starter-xxx 都在 spring-boot-starters 子模組中,且所有的 sp

Spring Boot原始碼分析@EnableAutoConfiguration註解(一)@AutoConfigurationImportSelector註解的處理

一、概述 @EnableAutoConfiguration註解是Spring Boot中配置自動裝載的總開關。本文將從@EnableAutoConfiguration入手,嘗試通過原始碼分析增強對Spring Boot的理解。   所用版本:Spring Boot 2.2.0.M5 + Spring

第四十章Spring Boot 自定義攔截器

ram obj pre .config factor ati bean configure 邏輯 1.首先編寫攔截器代碼 package com.sarnath.interceptor; import javax.servlet.http.HttpServlet

spring boot 原始碼解析57-actuator元件:info背後的密碼(全網獨家)

解析 我們平常訪問/info時會返回一些自定義的資訊,一般人只知道在application.properties中配置info.author=herry 開頭的配置,這樣就可以在訪問/info時,就會返回author: “herry”,但是如下的返回值是如何返

Spring原始碼閱讀populateBean實現 依賴注入原始碼解析

在完成Bean例項化後,Spring容器會給這個Bean注入相關的依賴Bean,在原始碼中,這一步通過類AbstractAutowireCapableBeanFactory中的populateBean方法完成。 測試程式碼 下面開始進入原始碼分析之前,先基於以下例項進行: /

spring boot原始碼解析

https://blog.csdn.net/dm_vincent/article/category/7079562https://blog.csdn.net/dm_vincent/article/details/76735888https://blog.csdn.net/dm

Spring實戰----原始碼解析SessionFactory及Session的管理及getCurrentSession的使用

在上一篇Hibernate5整合中當使用sessionFactory.getCurrentSession()時會報錯Could not obtain transaction-synchronized Session for current thread,本篇就從原始碼角度

spring boot 原始碼解析[email protected]

前言 之前在分析spring boot 原始碼時匯出可見@ConditionalOnBean 之類的註解,那麼它到底是如何使用的以及其工作流程如何,我們這裡就圍繞以下幾點來分析: @Conditional系列與Condition的關係 @Condition

spring boot 原始碼解析5-SpringApplication#run第5步

前言 之前的文章我們分析了SpringApplication#run方法執行的前4步,這裡我們分析第5步,列印banner. 解析 SpringApplication#run方法的第5步執行如下程式碼: private Banner printBa

spring boot 原始碼解析32-PublicMetrics詳解

前言 接下來的幾篇文章我們來分析一下spring-boot-actuator 中在org.springframework.boot.actuate.metrics中的程式碼,如圖: 這裡的程式碼不僅多,而且還比較複雜(類與類之間的關聯關係).我們的策略是

spring boot 原始碼解析2-SpringApplication初始化

前言 我們生成一個spring boot 專案時,會自帶一個啟動類. 程式碼如下: @SpringBootApplication public class DemoApplication { public static void main(St

Spring原始碼解析—— 結合SpringMVC過程理解IOC容器初始化之註解部分探究

前面的文章寫了xml中直接配置bean進行IOC的過程解析,接下來會針對註解進行IOC容器初始化的過程解析 因為會與之前的內容存在部分重疊,因此會針對相同的部分簡略帶過,針對不同的部分做重點說明:   一、Xml的配置和程式碼中的註解配置: applicationContext.xml配置新

Spring原始碼解析—— 簡單工廠模式的BeanFactory的超簡版實現

 一、什麼是簡單工廠模式 設計模式的核心是“分工”,通過分工將物件與職責劃分的更細化,進而提升系統設計的可擴充套件性,使其更容易維護。   開閉原則:對擴充套件開放,對修改關閉;要增加一個新的處理邏輯,可以開一個新的類,不要在老的上面修改 依賴倒轉原則:依賴關係從具體轉向抽象,也就是說:A

Spring原始碼解析FactoryBean-工廠方法模式的實現及使用

一、工廠方法模式中的三種模式的特點 工廠模式中的三種模式,分別是:簡單工廠模式、工廠方法模式、抽象工廠模式,三種分別是什麼,以及適合場景是什麼? (1)簡單工廠模式:一個抽象介面對應一個產品介面,特定產品實現這個介面,針對不同產品都可以在同一個工廠中生產,同一個工廠生產產品可以通過多種方式,單生產方法(通

Spring原始碼解析—— 策略模式在Spring中的應用

一、         什麼是策略模式 策略模式的定義/含義:策略本身就是為了實現某一個目標而採取的一種工作方式,因此只要能夠達成目標,則採取哪一種策略都可以;因此多種實際的策略之間是相互平行的。 注意:策略模式與模板模式是不同

Spring Boot系列(四):Spring Boot原始碼解析

一、自動裝配原理   之前博文已經講過,@SpringBootApplication繼承了@EnableAutoConfiguration,該註解匯入了AutoConfigurationImport Selector,這個類主要是掃描spring-boot-autoconfigure下面的META-INF\

spring源碼學習spring的AOP面向切面編程的實現解析

內部 遠程調用 關註 add aps 文件 uem 連接 row 一:Advice(通知)(1)定義在連接點做什麽,為切面增強提供織入接口。在spring aop中主要描述圍繞方法調用而註入的切面行為。(2)spring定義了幾個時刻織入增強行為的接口??=>org.