0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

什么是 SpringBoot?

jf_78858299 ? 來源:CSDN ? 作者:CSDN雙子孤狼 ? 2023-04-07 11:28 ? 次閱讀

前言如果我們想要使用傳統(tǒng)意義上的 Spring 應(yīng)用,那么需要配置大量的 xml 文件才可以啟動,而且隨著項目的越來越龐大,配置文件也會越來越繁瑣,這在一定程度上也給開發(fā)者帶來了困擾,于是 SpringBoot 就應(yīng)運而生了。

什么是 SpringBoot

2012 年 10 月,一個叫 Mike Youngstrom 的人在 Spring Jira 中創(chuàng)建了一個功能請求,要求在 Spring Framework 中支持無容器 Web 應(yīng)用程序體系結(jié)構(gòu),提出了在主容器引導(dǎo) Spring 容器內(nèi)配置 Web 容器服務(wù)。這件事情對 SpringBoot 的誕生應(yīng)該說是起到了一定的推動作用。

SpringBoot 的誕生就是為了簡化 Spring 中繁瑣的 XML 配置,其本質(zhì)依然是 Spring 框架,使用 SpringBoot 之后可以不使用任何 XML 配置來啟動一個服務(wù),使得我們在使用微服務(wù)架構(gòu)時可以更加快速的建立一個應(yīng)用。

SpringBoot 具有以下特點:

  • 創(chuàng)建獨立的 Spring 應(yīng)用。
  • 直接嵌入了 Tomcat、Jetty 或 Undertow(不需要部署 WAR 文件)。
  • 提供了固定的配置來簡化配置。
  • 盡可能地自動配置 Spring 和第三方庫。
  • 提供可用于生產(chǎn)的特性,如度量、運行狀況檢查和外部化配置。
  • 完全不需要生成代碼,也不需要 XML 配置。

SpringBoot 這些特點中最重要的兩條就是約定優(yōu)于配置和自動裝配。

約定優(yōu)于配置

SpringBoot的約定由于配置主要體現(xiàn)在以下方面:

maven 項目的配置文件存放在 resources 資源目錄下。maven 項目默認編譯后的文件放于 target 目錄。maven 項目默認打包成 jar 格式。配置文件默認為 application.yml 或者 application.yaml 或者 application.properties。默認通過配置文件 spring.profiles.active 來激活配置。

自動裝配

自動裝配則是 SpringBoot 的核心,自動裝配是如何實現(xiàn)的呢?為什么我們只要引入一個 starter 組件依賴就能實現(xiàn)自動裝配呢,接下來就讓我們一起來探討下 SpringBoot 的自動裝配機制。

相比較于傳統(tǒng)的 Spring 應(yīng)用,搭建一個 SpringBoot 應(yīng)用,我們只需要引入一個注解 @SpringBootApplication,就可以成功運行。

我們就從 SpringBoot 的這個注解開始入手,看看這個注解到底替我們做了什么。圖片

前面四個不用說,是定義一個注解所必須的,關(guān)鍵就在于后面三個注解:@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan。也就是說我們?nèi)绻挥?@SpringBootApplication 這個復(fù)合注解,而是直接使用最下面這三個注解,也能啟動一個 SpringBoot 應(yīng)用。

@SpringBootConfiguration 注解

[這個注解我們點進去就可以發(fā)現(xiàn),它實際上就是一個 @Configuration 注解,這個注解大家應(yīng)該很熟悉了,加上這個注解就是為了讓當前類作為一個配置類交由SpringIOC 容器進行管理,因為前面我們說了,SpringBoot 本質(zhì)上還是 Spring,所以原屬于 Spring 的注解 @ConfigurationSpringBoot 中也可以直接應(yīng)用。

@ComponentScan 注解

[這個注解也很熟悉,用于定義 Spring 的掃描路徑,等價于在 xml 文件中配置 context:component-scan,假如不配置掃描路徑,那么 Spring 就會默認掃描當前類所在的包及其子包中的所有標注了 @Component,@Service,@Controller 等注解的類。

@EnableAutoConfiguration

這個注解才是實現(xiàn)自動裝配的關(guān)鍵,點進去之后發(fā)現(xiàn),它是一個由@AutoConfigurationPackage@Import 注解組成的復(fù)合注解。圖片

@EnableXXX 注解也并不是 SpringBoot 中的新注解,這種注解在 Spring 3.1 版本就開始出現(xiàn)了,比如開啟定時任務(wù)的注解 @EnableScheduling 等。

@Import 注解

[這個注解比較關(guān)鍵,我們通過一個例子來說明一下。

定義一個普通類TestImport,不加任何注解,我們知道這個時候這個類并不會被 Spring 掃描到,也就是無法直接注入這個類:

public class TestImport {
}

現(xiàn)實開發(fā)中,假如就有這種情況,定義好了一個類,即使加上了注解,也不能保證這個類一定被 Spring 掃描到,這個時候該怎么做呢?

這時候我們可以再定義一個類 MyConfiguration,保證這個類可以被 Spring 掃描到,然后通過加上 @Import 注解來導(dǎo)入 TestImport 類,這時候就可以直接注入 TestImport 了:

@Configuration
@Import(TestImport.class)
public class MyConfiguration {
}

所以這里的 @Import 注解其實就是為了去導(dǎo)入一個類 AutoConfigurationImportSelector,接下來我們需要分析一下這個類。

AutoConfigurationImportSelector 類

進入這個類之后,有一個方法,這個方法很好理解,首先就是看一下 AnnotationMetadata(注解的元信息),有沒有數(shù)據(jù),沒有就說明沒導(dǎo)入直接返回一個空數(shù)組,否則就調(diào)用 getAutoConfigurationEntry 方法:圖片

進入 getAutoConfigurationEntry 方法:

圖片

這個方法里面就是通過調(diào)用 getCandidateConfigurations 來獲取候選的 Bean,并將其存為一個集合,最后經(jīng)過去重,校驗等一系列操作之后,被封裝成 AutoConfigurationEntry 對象返回。

繼續(xù)進入 getCandidateConfigurations 方法,這時候就幾乎看到曙光了:圖片

這里面再繼續(xù)點擊去就沒必要了,看錯誤提示大概就知道了,loadFactoryNames 方法會去 META-INF/spring.factories 文件中根據(jù) EnableAutoConfiguration 的全限定類名獲取到我們需要導(dǎo)入的類,而 EnableAutoConfiguration 類的全限定類名為 org.springframework.boot.autoconfigure.EnableAutoConfiguration,那么就讓我們打開這個文件看一下:圖片

可以看到,這個文件中配置了大量的需要自動裝配的類,當我們啟動 SpringBoot 項目的時候,SpringBoot會掃描所有jar 包下面的 META-INF/spring.factories 文件,并根據(jù) key 值進行讀取,最后在經(jīng)過去重等一些列操作得到了需要自動裝配的類。

需要注意的是:上圖中的 spring.factories 文件是在 spring-boot-autoconfigure 包下面,這個包記錄了官方提供的 stater 中幾乎所有需要的自動裝配類,所以并不是每一個官方的 starter 下都會有 spring.factories 文件。

談?wù)?SPI 機制

通過 SpringFactoriesLoader來讀取配置文件 spring.factories 中的配置文件的這種方式是一種 SPI 的思想。那么什么是 SPI 呢?

SPI,Service Provider Interface。即:接口服務(wù)的提供者。就是說我們應(yīng)該面向接口(抽象)編程,而不是面向具體的實現(xiàn)來編程,這樣一旦我們需要切換到當前接口的其他實現(xiàn)就無需修改代碼。

Java 中,數(shù)據(jù)庫驅(qū)動就使用到了 SPI 技術(shù),每次我們只需要引入數(shù)據(jù)庫驅(qū)動就能被加載的原因就是因為使用了 SPI 技術(shù)。

打開 DriverManager 類,其初始化驅(qū)動的代碼如下:

圖片

進入 ServiceLoader 方法,發(fā)現(xiàn)其內(nèi)部定義了一個變量:

private static final String PREFIX = "META-INF/services/";

這個變量在下面加載驅(qū)動的時候有用到,下圖中的 servicejava.sql.Driver

圖片

所以就是說,在數(shù)據(jù)庫驅(qū)動的 jar 包下面的 META-INF/services/ 下有一個文件 java.sql.Driver,里面記錄了當前需要加載的驅(qū)動,我們打開這個文件可以看到里面記錄的就是驅(qū)動的全限定類名:

圖片

@AutoConfigurationPackage 注解

從這個注解繼續(xù)點進去之后可以發(fā)現(xiàn),它最終還是一個 @Import 注解:

圖片

這個時候它導(dǎo)入了一個 AutoConfigurationPackages 的內(nèi)部類 Registrar, 而這個類其實作用就是讀取到我們在最外層的 @SpringBootApplication 注解中配置的掃描路徑(沒有配置則默認當前包下),然后把掃描路徑下面的類都加到數(shù)組中返回。

圖片

手寫一個 stater 組件

了解完自動裝配的原理,接下來就可以動手寫一個自己的 starter 組件了。

starter 組件命名規(guī)則

SpringBoot 官方的建議是,如果是我們開發(fā)者自己開發(fā)的 starter 組件(即屬于第三方組件),那么命名規(guī)范是{name}-spring-boot-starter,而如果是 SpringBoot 官方自己開發(fā)的組件,則命名為 spring-boot-starter-{name}。

當然,這只是一個建議,如果非不按這個規(guī)則也沒什么問題,但是為了更好的識別區(qū)分,還是建議按照這個規(guī)則來命名。

手寫 starter

寫一個非常簡單的組件,這個組件只做一件事,那就是實現(xiàn) fastjson 序列化。

  • 新建一個 SpringBoot 應(yīng)用 lonelyWolf-spring-boot-starter。
  • 修改 pom 文件,并新增 fastjson 依賴(省略了部分屬性)。
<parent>
    <groupId>org.springframework.boot<span class="hljs-name"groupId>
    <artifactId>spring-boot-starter-parent<span class="hljs-name"artifactId>
    <version>2.4.0<span class="hljs-name"version>
    <relativePath/>
<span class="hljs-name"parent>

<groupId>com.lonely.wolf.note<span class="hljs-name"groupId>
<artifactId>lonelyWolf-spring-boot-starter<span class="hljs-name"artifactId>
<version>1.0.0-SNAPSHOT<span class="hljs-name"version>

<dependencies>
    <dependency>
      <groupId>org.springframework.boot<span class="hljs-name"groupId>
      <artifactId>spring-boot-starter<span class="hljs-name"artifactId>
    <span class="hljs-name"dependency>

    <dependency>
      <groupId>com.alibaba<span class="hljs-name"groupId>
      <artifactId>fastjson<span class="hljs-name"artifactId>
      <version>1.2.72<span class="hljs-name"version>
    <span class="hljs-name"dependency>
<span class="hljs-name"dependencies>
  • 新建一個序列化類 JsonSerial 類來實現(xiàn) fastjson 序列化。
public class JsonSerial {
    public
  • 新建一個自動裝配類 MyAutoConfiguration 來生成 JsonSerial
@Configuration
public class MyAutoConfiguration {

    @Bean
    public JsonSerial jsonSerial(){
        return new JsonSerial();
    }
}
  • 完成之后將其打成一個 jar 包,然后再另一個 SpringBoot 中引入依賴:
<dependency>
     <groupId>com.lonely.wolf.note<span class="hljs-name"groupId>
     <artifactId>lonelyWolf-spring-boot-starter<span class="hljs-name"artifactId>
     <version>1.0.0-SNAPSHOT<span class="hljs-name"version>
<span class="hljs-name"dependency>
  • 這時候在這個 SpringBoot 應(yīng)用中直接注入 JsonSerial 對象會直接提示找不到這個對象:

圖片

這是因為 MyAutoConfiguration 這個類是在外部 jar 包之中,并沒有被掃描到(需要注意的是,假如剛好 jar 包的路徑和掃描的路徑相同,那么是可以被掃描到的,但是在實際項目中,我們不可能確保引入的 jar 包能被掃描到,所以才需要通過配置的方式來導(dǎo)入),所以我們還需要導(dǎo)入這個外部配置類。

  • resources 目錄下新建一個文件 META-INF/spring.factories 文件,文件內(nèi)新增一個如下配置:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\\
com.lonely.wolf.note.MyAutoConfiguration

這樣,SpringBoot 就會將 MyAutoConfiguration 進行管理,從而得到 JsonSerial 對象,這樣就可以直接注入使用了。

總結(jié)

本文從為什么要有 SpringBoot,以及 SpringBoot 到底方便在哪里開始入手,逐步分析了 SpringBoot 自動裝配的原理,最后手寫了一個簡單的 start 組件,通過實戰(zhàn)來體會了 SpringBoot 自動裝配機制的奧妙。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • JAVA
    +關(guān)注

    關(guān)注

    19

    文章

    2943

    瀏覽量

    104089
  • spring
    +關(guān)注

    關(guān)注

    0

    文章

    335

    瀏覽量

    14257
  • 自動裝配
    +關(guān)注

    關(guān)注

    0

    文章

    7

    瀏覽量

    635
  • SpringBoot
    +關(guān)注

    關(guān)注

    0

    文章

    172

    瀏覽量

    145
收藏 人收藏

    評論

    相關(guān)推薦

    SpringBoot配置Mybatis的2個錯誤和修正

    SpringBoot】配置Mybatis錯誤
    發(fā)表于 04-19 10:31

    SpringBoot中的Druid介紹

    SpringBoot中Druid數(shù)據(jù)源配置
    發(fā)表于 05-07 09:21

    基于SpringBoot mybatis方式的增刪改查實現(xiàn)

    SpringBoot mybatis方式實現(xiàn)增刪改查
    發(fā)表于 06-18 16:56

    SpringBoot知識總結(jié)

    SpringBoot干貨學習總結(jié)
    發(fā)表于 08-01 10:40

    springboot spring data jpa使用總結(jié)

    【本人禿頂程序員】springboot專輯:spring data jpa的使用
    發(fā)表于 04-15 11:38

    怎么學習SpringBoot

    SpringBoot學習之路(X5)- 整合JPA
    發(fā)表于 06-10 14:52

    SpringBoot 學習筆記

    SpringBoot 學習筆記 【整合JWT】添加依賴創(chuàng)建工具類登錄獲取jwt使用jwtDemo源碼參考資料添加依賴pom.xml...com.auth0java-jwt3.12.0
    發(fā)表于 07-01 07:27

    springboot集成mqtt

    springboot集成mqtt,大綱一.數(shù)據(jù)入庫1.數(shù)據(jù)入庫解決方案二.開發(fā)實時訂閱發(fā)布展示頁面1.及時通訊技術(shù)2.技術(shù)整合
    發(fā)表于 07-16 07:53

    怎樣去使用springboot

    怎樣去使用springboot呢?學習springboot需要懂得哪些?
    發(fā)表于 10-25 07:13

    SpringBoot嵌入式Servlet容器啟動原理是什么

    SpringBoot嵌入式Servlet容器啟動原理思維導(dǎo)圖
    發(fā)表于 12-20 07:26

    SpringBoot應(yīng)用啟動運行run方法

    什么時候創(chuàng)建嵌入式的Servlet容器工廠?什么時候獲取嵌入式的Servlet容器并啟動Tomcat;獲取嵌入式的Servlet容器工廠:1)、SpringBoot應(yīng)用啟動運行run方法2
    發(fā)表于 12-20 06:16

    SpringBoot配置嵌入式Servlet

    SpringBoot配置嵌入式Servlet容器定制和修改Servlet容器相關(guān)配置全局配置文件編寫WebServerFactoryCustomizer注冊Servlet三大組件注冊Servlet
    發(fā)表于 12-20 06:19

    SpringBoot實現(xiàn)多線程

    SpringBoot實現(xiàn)多線程
    的頭像 發(fā)表于 01-12 16:59 ?1708次閱讀
    <b class='flag-5'>SpringBoot</b>實現(xiàn)多線程

    SpringBoot的核心注解1

    今天跟大家來探討下SpringBoot的核心注解@SpringBootApplication以及run方法,理解下springBoot為什么不需要XML,達到零配置
    的頭像 發(fā)表于 04-07 14:34 ?607次閱讀
    <b class='flag-5'>SpringBoot</b>的核心注解1

    SpringBoot的核心注解2

    今天跟大家來探討下SpringBoot的核心注解@SpringBootApplication以及run方法,理解下springBoot為什么不需要XML,達到零配置
    的頭像 發(fā)表于 04-07 14:34 ?1870次閱讀
    <b class='flag-5'>SpringBoot</b>的核心注解2