深入理解SpringBoot核心原理--------啟動機制(starter機制)

一、前言

使用過springboot的同學應該已經知道,springboot透過預設配置了很多框架的使用方式幫我們大大簡化了專案初始搭建以及開發過程。本文的目的就是一步步分析springboot的啟動過程,這次主要是分析springboot特性自動裝配。

那麼首先帶領大家回顧一下以往我們的web專案是如何搭建的,通常我們要搭建一個基於Spring的Web應用,我們需要做以下一些工作:

1。pom檔案中引入相關jar包,包括spring、springmvc、redis、mybaits、log4j、mysql-connector-java 等等相關jar 。。。

2。配置web。xml,Listener配置、Filter配置、Servlet配置、log4j配置、error配置 。。。

3。配置資料庫連線、配置spring事務

4。配置檢視解析器

5。開啟註解、自動掃描功能  6。配置完成後部署tomcat、啟動除錯

……

花在搭建一個初始專案,可能一個小時就過去了或者半天救過了,但是用了SpringBoot之後一切都會變得非常便捷,下面我們首先來分析一下SpringBoot的起步依賴以及自動配置。

二、起步依賴

1。在我們的pom檔案裡面引入以下jar:

spring-boot-starter-web包自動幫我們引入了web模組開發需要的相關jar包。

mybatis-spring-boot-starter幫我們引入了dao開發相關的jar包。

spring-boot-starter-xxx是官方提供的starter,xxx-spring-boot-starter是第三方提供的starter。

截圖看一下我們的mybatis-spring-boot-starter

可以看出mybatis-spring-boot-starter並沒有任何原始碼,只有一個pom檔案,它的作用就是幫我們引入其它jar。

2。配置資料來源

stater機制幫我們完成了專案起步所需要的的相關jar包。那問題又來了,傳統的spring應用中不是要在application。xml中配置很多bean的嗎,比如dataSource的配置,transactionManager的配置 。。。 springboot是如何幫我們完成這些bean的配置的?下面我們來分析這個過程

三、自動配置——————

1。基於java程式碼的bean配置

以mybatis為例,在上面的截圖中,我們發現mybatis-spring-boot-starter這個包幫我們引入了mybatis-spring-boot-autoconfigure這個包,如下圖:

深入理解SpringBoot核心原理--------啟動機制(starter機制)

裡面有MybatisAutoConfiguration這個類,開啟這個類看看有些什麼東西。

深入理解SpringBoot核心原理--------啟動機制(starter機制)

熟悉@Configuration&、@Bean這兩個bean的同學或許已經知道了。這兩個註解一起使用就可以建立一個基於java程式碼的配置類,可以用來替代相應的xml配置檔案。

@Configuration註解的類可以看作是能生產讓Spring IoC容器管理的Bean例項的工廠。

@Bean註解告訴Spring,一個帶有@Bean的註解方法將返回一個物件,該物件應該被註冊到spring容器中。

所以上面的MybatisAutoConfiguration這個類,自動幫我們生成了SqlSessionFactory這些Mybatis的重要例項並交給spring容器管理,從而完成bean的自動註冊。

2。自動配置條件依賴

從MybatisAutoConfiguration這個類中使用的註解可以看出,要完成自動配置是有依賴條件的。

首先預習一下Springboot是常用的條件依賴註解有:

@ConditionalOnBean,僅在當前上下文中存在某個bean時,才會例項化這個Bean。

@ConditionalOnClass,某個class位於類路徑上,才會例項化這個Bean。

@ConditionalOnExpression,當表示式為true的時候,才會例項化這個Bean。

@ConditionalOnMissingBean,僅在當前上下文中不存在某個bean時,才會例項化這個Bean。

@ConditionalOnMissingClass,某個class在類路徑上不存在的時候,才會例項化這個Bean。

@ConditionalOnNotWebApplication,不是web應用時才會例項化這個Bean。

@AutoConfigureAfter,在某個bean完成自動配置後例項化這個bean。

@AutoConfigureBefore,在某個bean完成自動配置前例項化這個bean。

深入理解SpringBoot核心原理--------啟動機制(starter機制)

3。Bean引數的獲取

到此我們已經知道了bean的配置過程,但是還沒有看到springboot是如何讀取yml或者properites配置檔案的的屬性來建立資料來源的?

在DataSourceAutoConfiguration類裡面,我們注意到使用了EnableConfigurationProperties這個註解。

DataSourceProperties中封裝了資料來源的各個屬性,且使用了註解ConfigurationProperties指定了配置檔案的字首。

透過以上分析,我們可以得知:

@ConfigurationProperties註解的作用是把yml或者properties配置檔案轉化為bean。

@EnableConfigurationProperties註解的作用是使@ConfigurationProperties註解生效。如果只配置@ConfigurationProperties註解,在spring容器中是獲取不到yml或者properties配置檔案轉化的bean的。

透過這種方式,把yml或者properties配置引數轉化為bean,這些bean又是如何被發現與載入的?

3。Bean的發現

springboot預設掃描啟動類所在的包下的主類與子類的所有元件,但並沒有包括依賴包的中的類,那麼依賴包中的bean是如何被發現和載入的?

我們通常在啟動類中加@SpringBootApplication這個註解,點進去看

實際上重要的只有三個Annotation:

@Configuration(@SpringBootConfiguration裡面還是應用了@Configuration)

@EnableAutoConfiguration

@ComponentScan

@Configuration的作用上面我們已經知道了,被註解的類將成為一個bean配置類。

@ComponentScan的作用就是自動掃描並載入符合條件的元件,比如@Component和@Repository等,最終將這些bean定義載入到spring容器中。

@EnableAutoConfiguration 這個註解的功能很重要,藉助@Import的支援,收集和註冊依賴包中相關的bean定義。

如上原始碼,@EnableAutoConfiguration註解引入了@AutoConfigurationPackage和@Import這兩個註解。@AutoConfigurationPackage的作用就是自動配置的包,@Import匯入需要自動配置的元件。

new AutoConfigurationPackages。PackageImport(metadata))。getPackageName()

new AutoConfigurationPackages。PackageImport(metadata)

這兩句程式碼的作用就是載入啟動類所在的包下的主類與子類的所有元件註冊到spring容器,這就是前文所說的springboot預設掃描啟動類所在的包下的主類與子類的所有元件。

那問題又來了,要蒐集並註冊到spring容器的那些beans來自哪裡?

進入 AutoConfigurationImportSelector類,

我們可以發現SpringFactoriesLoader。loadFactoryNames方法呼叫loadSpringFactories方法從所有的jar包中讀取META-INF/spring。factories檔案資訊。

每個xxxAutoConfiguration都是一個基於java的bean配置類。實際上,這些xxxAutoConfiguratio不是所有都會被載入,會根據xxxAutoConfiguration上的@ConditionalOnClass等條件判斷是否載入;透過反射機制將spring。factories中@Configuration類例項化為對應的java實列。

到此我們已經知道怎麼發現要自動配置的bean了,最後一步就是怎麼樣將這些bean載入到spring容器。

4。Bean 載入

如果要讓一個普通類交給Spring容器管理,通常有以下方法:

1、使用 @Configuration與@Bean 註解

2、使用@Controller @Service @Repository @Component 註解標註該類,然後啟用@ComponentScan自動掃描

3、使用@Import 方法

springboot中使用了@Import 方法

@EnableAutoConfiguration註解中使用了@Import()註解,AutoConfigurationImportSelector實現了DeferredImportSelector介面,

DeferredImportSelector介面繼承了ImportSelector介面,ImportSelector介面只有一個selectImports方法。

selectImports方法返回一組bean,@EnableAutoConfiguration註解藉助@Import註解將這組bean注入到spring容器中,springboot正式透過這種機制來完成bean的注入的。

四、總結

我們可以將自動配置的關鍵幾步以及相應的註解總結如下:

1、@Configuration&與@Bean————>>>基於java程式碼的bean配置

2、@Conditional————>>>>>>設定自動配置條件依賴

3、@EnableConfigurationProperties與@ConfigurationProperties->讀取配置檔案轉換為bean。

4、@EnableAutoConfiguration、@AutoConfigurationPackage 與@Import->實現bean發現與載入。

TAG: beanSpring註解配置