- 一、SpringBoot的starter簡介 -
1。1 什麼是starter(場景啟動器)
在SpringBoot出現之前,如果我們想使用SpringMVC來構建我們的web專案,必須要做的幾件事情如下:
1、首先專案中需要引入SpringMVC的依賴
2、在web。xml中註冊SpringMVC的DispatcherServlet,並配置url對映
3、編寫springmcv-servlet。xml,在其中配置SpringMVC中幾個重要的元件,處理對映器(HandlerMapping)、處理介面卡(HandlerAdapter)、檢視解析器(ViewResolver)
4、在applicationcontext。xml檔案中引入springmvc-servlet。xml檔案
…
以上這幾步只是配置好了SpringMVC,如果我們還需要與資料庫進行互動,就要在application。xml中配置資料庫連線池DataSource,如果需要資料庫事務,還需要配置TransactionManager…
這就是使用Spring框架開發專案帶來的一些的問題:
**依賴匯入問題:**每個專案都需要來單獨維護自己所依賴的jar包,在專案中使用到什麼功能就需要引入什麼樣的依賴。手動匯入依賴容易出錯,且無法統一集中管理
**配置繁瑣:**在引入依賴之後需要做繁雜的配置,並且這些配置是每個專案來說都是必要的,例如web。xml配置(Listener配置、Filter配置、Servlet配置)、log4j配置、資料庫連線池配置等等。這些配置重複且繁雜,在不同的專案中需要進行多次重複開發,這在很大程度上降低了我們的開發效率
而在SpringBoot出現之後,它為我們提供了一個強大的功能來解決上述的兩個痛點,這就是SpringBoot的starters(場景啟動器)。Spring Boot透過將我們常用的功能場景抽取出來,做成的一系列場景啟動器,這些啟動器幫我們匯入了實現各個功能所需要依賴的全部元件,我們只需要在專案中引入這些starters,相關場景的所有依賴就會全部被匯入進來,並且我們可以拋棄繁雜的配置,僅需要透過配置檔案來進行少量的配置就可以使用相應的功能。
- 二、SpringBoot場景啟動器的原理 -
在匯入的starter之後,SpringBoot主要幫我們完成了兩件事情:
相關元件的自動匯入
相關元件的自動配置
這兩件事情統一稱為SpringBoot的自動配置
2。1 自動配置原理
2。1。1 自動配置類的獲取與注入
我們從主程式入口來探索一下整個過程的原理:
@SpringBootApplication //標註這個類是一個springboot的應用
public class CommunityApplication {
public static void main(String[] args) {
//將springboot應用啟動
SpringApplication。run(CommunityApplication。class, args);
}
}
@SpringBootApplication註解內部結構如下圖所示:
AutoConfigurationImportSelector :重點看該類中重寫的selectImports方法,看下它返回的字串陣列是如何得來的:
我們可以去到上邊提到的spring。factories檔案中去看一下,找到spring官方提供的spring-boot-autoconfigure包,在其下去找一下該檔案:
可以看到這個就是SpringBoot官方為我們提供的所有自動配置類的候選列表。我們可以在其中找到一個我們比較熟悉的自動配置類去看一下它內部的實現:
可以看到這些一個個的都是JavaConfig配置類,而且都透過@Bean註解向容器中注入了一些Bean
結論:
SpringBoot在啟動的時候從類路徑下的META-INF/spring。factories中獲取EnableAutoConfiguration指定的所有自動配置類的全限定類名
將這些自動配置類匯入容器 , 自動配置類就生效 , 幫我們進行自動配置工作;
整個J2EE的整體解決方案和自動配置都在spring-boot-autoconfigure的jar包中;
它會給容器中匯入非常多的自動配置類 (xxxAutoConfiguration), 就是給容器中匯入這個場景需要的所有元件 , 並配置好這些元件 ;
有了自動配置類 , 免去了我們手動編寫配置注入功能元件等的工作;
2。1。2 自動配置的過程
自動配置類被注入到容器當中後,會幫我們進行元件的自動配置和自動注入的工作,我們以HttpEncodingAutoConfiguration(Http編碼自動配置)為例解釋這個過程:
首先我們先看下SpringBoot中配置檔案與POJO類之間對映的方法,這是進行自動配置的基礎。
配置集中化管理
:SpringBoot中所有可配置項都集中在一個檔案中(application。yml),這個檔案中的配置透過@ConfigurationProperties註解來與我們程式內部定義的POJO類來產生關聯,這些POJO類統一命名為xxxProperties,並且這些xxxProperties類中各個屬性欄位都有自己的預設值,這也是SpringBoot約定大於配置理念的體現,儘可能減少使用者做選擇的次數,但同時又不失靈活性。只要我們想,配置檔案中的配置隨時可以覆蓋預設值。
之後,透過配合@EnableConfigurationProperties註解,就可以自動將與配置檔案繫結好的這個類注入到容器中供我們使用。
自動配置類的工作流程:
根據限定的條件向容器中注入元件
使用xxxProperties對注入的元件的相關屬性進行配置
//表示這是一個配置類,和以前編寫的配置檔案一樣,也可以給容器中新增元件;
@Configuration
//將與配置檔案繫結好的某個類注入到容器中,使其生效
//進入這個HttpProperties檢視,將配置檔案中對應的值和HttpProperties繫結起來;
//並把HttpProperties加入到ioc容器中
@EnableConfigurationProperties(HttpProperties。class)
//Spring底層@Conditional註解
//根據不同的條件判斷,如果滿足指定的條件,整個配置類裡面的配置就會生效;
//這裡的意思就是判斷當前應用是否是web應用,如果是,當前配置類生效
@ConditionalOnWebApplication(
type
= ConditionalOnWebApplication。Type。SERVLET)
//判斷系統中有沒有CharacterEncodingFilter這個類,如果有配置類才生效
@ConditionalOnClass(CharacterEncodingFilter。class)
//判斷配置檔案中是否存在某個配置:spring。http。encoding。enabled;
//matchIfMissing =
true
表明即使我們配置檔案中不配置pring。http。encoding。enabled=
true
,該配置類也是預設生效的;
@ConditionalOnProperty(prefix =
“spring。http。encoding”
, value =
“enabled”
, matchIfMissing =
true
)
public class HttpEncodingAutoConfiguration {
//該類已經與配置檔案綁定了
private final HttpProperties。Encoding properties;
//構建該自動配置類時將與配置檔案繫結的配置類作為入參傳遞進去
public HttpEncodingAutoConfiguration(HttpProperties properties) {
this。properties = properties。getEncoding();
}
@Bean
@ConditionalOnMissingBean
public CharacterEncodingFilter
characterEncodingFilter
() {
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter。setEncoding(this。properties。getCharset()。name()); //注入bean時使用配置類中屬性的值進行初始化,相當於將配置檔案中的值對映到了元件的某些屬性上
filter。setForceRequestEncoding(this。properties。shouldForce(Type。REQUEST));
filter。setForceResponseEncoding(this。properties。shouldForce(Type。RESPONSE));
return
filter; //注入配置好的bean
}
}
一句話總結下自動配置類的工作過程 :
首先容器會根據當前不同的條件判斷,決定這個配置類是否生效!
一但這個配置類生效;這個配置類就會給容器中新增相應元件;
這些元件的屬性是從對應的properties類中獲取的,這些類裡面的每一個屬性又是和配置檔案繫結的;
所有在配置檔案中能配置的屬性都是在xxxxProperties類中封裝著,配置檔案可以配置什麼內容,可以參照該字首對應的屬性類中的屬性欄位
//從配置檔案中獲取指定的值和bean的屬性進行繫結
@ConfigurationProperties(prefix =
“spring。http”
)
public class HttpProperties {
// 。。。。。
}
2。2 SpringBoot自動配置使用總結
1、SpringBoot啟動會載入大量的自動配置類
2、我們首先可以看我們需要的功能有沒有在SpringBoot預設寫好的自動配置類當中;
3、我們再來看這個自動配置類中到底配置了哪些元件;(只要我們要用的元件存在在其中,我們就不需要再手動配置了)
4、給容器中自動配置類新增元件的時候,會從properties類中獲取某些屬性。我們只需要在配置檔案中指定這些屬性的值即可;
xxxxAutoConfigurartion
:自動配置類;給容器中新增元件
xxxxProperties
:封裝配置檔案中相關屬性;
瞭解完自動裝配的原理後,我們來關注一個細節問題,
自動配置類必須在一定的條件下才能生效
;
@Conditional派生註解(Spring註解版原生的@Conditional作用)
作用:必須是@Conditional指定的條件成立,才給容器中新增元件,配置裡面的所有內容才生效;
@Conditional擴充套件註解
作用(判斷是否滿足當前條件)
@ConditionalOnNotWebApplication
當前不是web環境
@ConditionalOnWebApplication
當前是web環境
@ConditionalOnResource
類路徑下是否有指定資原始檔
@ConditionalOnExpression
滿足SpEL表示式指定
@ConditionalOnMissingBean
容器中不存在指定的Bean
@ConditionalOnBean
容器中是否存在指定的Bean
@ConditionalOnSingleCandidate
容器中只有一個指定的Bean,或者這個Bean是首選Bean
@ConditionalOnJava
系統的java版本是否符合要求
@ConditionalOnMissingClass
系統中沒有指定的類
@ConditionalOnClass
系統中有指定的類
@ConditionalOnProperty
系統中指定的屬性是否有指定的值
那麼多的自動配置類,必須在一定的條件下才能生效;也就是說,我們載入了這麼多的配置類,但不是所有的都生效了。
我們怎麼知道哪些自動配置類生效?
我們可以透過啟用 debug=true屬性;來讓控制檯列印自動配置報告,這樣我們就可以很方便的知道哪些自動配置類生效;
#在配置檔案中開啟springboot的除錯類
debug=
true
Positive matches:(自動配置類啟用的:正匹配)
Positive matches:
————————-
AopAutoConfiguration matched:
- @ConditionalOnClass found required classes
‘org。springframework。context。annotation。EnableAspectJAutoProxy’
,
‘org。aspectj。lang。annotation。Aspect’
,
‘org。aspectj。lang。reflect。Advice’
,
‘org。aspectj。weaver。AnnotatedElement’
(OnClassCondition)
- @ConditionalOnProperty (spring。aop。auto=
true
) matched (OnPropertyCondition)
AopAutoConfiguration。CglibAutoProxyConfiguration matched:
- @ConditionalOnProperty (spring。aop。proxy-target-class=
true
) matched (OnPropertyCondition)
AuditAutoConfiguration
#auditListener matched:
- @ConditionalOnMissingBean (types: org。springframework。boot。actuate。audit。listener。AbstractAuditListener; SearchStrategy: all) did not find any beans (OnBeanCondition)
AuditAutoConfiguration
#authenticationAuditListener matched:
- @ConditionalOnClass found required class
‘org。springframework。security。authentication。event。AbstractAuthenticationEvent’
(OnClassCondition)
- @ConditionalOnMissingBean (types: org。springframework。boot。actuate。security。AbstractAuthenticationAuditListener; SearchStrategy: all) did not find any beans (OnBeanCondition)
Negative matches:(沒有啟動,沒有匹配成功的自動配置類:負匹配)
Negative matches:
————————-
ActiveMQAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class
‘javax。jms。ConnectionFactory’
(OnClassCondition)
AopAutoConfiguration。JdkDynamicAutoProxyConfiguration:
Did not match:
- @ConditionalOnProperty (spring。aop。proxy-target-class=
false
) did not find property
‘proxy-target-class’
(OnPropertyCondition)
AppOpticsMetricsExportAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class
‘io。micrometer。appoptics。AppOpticsMeterRegistry’
(OnClassCondition)
ArtemisAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class
‘javax。jms。ConnectionFactory’
(OnClassCondition)
Exclusions、Unconditional classes(排除的、沒有限定條件的自動配置類):
Exclusions:
——————-
org。springframework。boot。autoconfigure。jdbc。DataSourceAutoConfiguration
Unconditional classes:
————————————
org。springframework。boot。autoconfigure。context。ConfigurationPropertiesAutoConfiguration
org。springframework。boot。actuate。autoconfigure。endpoint。jmx。JmxEndpointAutoConfiguration
org。springframework。boot。actuate。autoconfigure。health。HealthIndicatorAutoConfiguration
org。springframework。boot。actuate。autoconfigure。info。InfoContributorAutoConfiguration
- 三、自定義場景啟動器 -
現在我們已經瞭解了場景啟動器的概念以及其隱藏在背後的自動配置的原理,我們就可以自己來對SpringBoot進行功能拓展,定義我們自己的場景啟動器。
3。1 starter的命名規範
官方名稱空間
字首:spring-boot-starter-
模式:spring-boot-starter-模組名
舉例:spring-boot-starter-web、spring-boot-starter-jdbc
自定義名稱空間
字尾:-spring-boot-starter
模式:模組-spring-boot-starter
舉例:mybatis-spring-boot-starter
3。2 starter模組整體結構
透過上邊的介紹,可以總結starter的整體實現邏輯主要由兩個基本部分組成:
xxxAutoConfiguration
:自動配置類,對某個場景下需要使用到的一些元件進行自動注入,並利用xxxProperties類來進行元件相關配置
xxxProperties
:某個場景下所有可配置屬性的整合,在配置檔案中配置可以進行屬性值的覆蓋
按照SpringBoot官方的定義,Starer的作用就是依賴聚合,因此直接在starter內部去進行程式碼實現是不符合規定的,starter應該只起到依賴匯入的作用,而具體的程式碼實現應該去交給其他模組來實現,然後在starter中去引用該模組即可,因此整體的starter的構成應該如下圖所示:
可見starter模組依賴了兩部分,一部分是一些常用依賴,另一部分就是對自動配置模組的依賴,而xxxAutoConfiguration與xxxProperties的具體實現,都封裝在自動配置模組中,starter實際是透過該模組來對外提供相應的功能。
3。3 autoconfigure模組開發
3。3。1 依賴引入
首先所有的自動配置模組都要引入兩個jar包依賴:
true
其他依賴的選擇根據專案需要進行新增即可
3。3。2 xxxAutoConfiguration的實現
autoconfigure模組中最重要的就是自動配置類的編寫,它為我們實現元件的自動配置與自動注入。
在編寫自動配置類的時候,我們應該要考慮向容器中注入什麼元件,如何去配置它。
@Configuration
@ConditionalOnxxx
@ConditionalOnxxx//限定自動配置類生效的一些條件
@EnableConfigurationProperties(xxxProperties。class)
public class xxxAutoConfiguration {
@Autowired
private xxxProperties properties;
@Bean
public static BeanYouNeed
beanYouNeed
() {
BeanYouNeed bean = new BeanYouNeed()
bean。setField(properties。get(field));
bean。setField(properties。get(field));
bean。setField(properties。get(field));
……
}
}
3。3。3 xxxProperties的實現
這是跟配置檔案相繫結的類,裡邊的屬性就是我們可以在配置檔案中配置的內容,然後透過@ConfigurationProperties將其與配置檔案繫結:
@ConfigurationProperties(prefix =
“your properties”
) //使用@ConfigurationProperties註解繫結配置檔案
public class xxxProperties {
private boolean enabled =
true
;
private String clientId;
private String beanName;
private String scanBasePackage;
private String path;
private String token;
}
3。3。4 配置spring。factories檔案
在resource目錄下新建META-INF資料夾,在資料夾下新建
spring.factories
檔案,並新增寫好的xxxAutoConfiguration類:
org。springframework。boot。autoconfigure。EnableAutoConfiguration=\
com。meituan。xframe。boot。mcc。autoconfigure。xxxAutoConfiguration
3。4 Starter模組開發
starter模組中只進行依賴匯入,在pom檔案中新增對autoconfigure模組的依賴,並新增一些其他必要的依賴項:
================================================================
添加了對autoconfigure模組的引用
===============================================================
其他的一些必要依賴項
這兩個模組都開發完成之後,透過mvn install命令或者deploy命令將包釋出到本地或者中央倉庫,即可直接在其他專案中引用我們自定義的starter模組了
作者 | 威尼斯的淚H來源 | csdn。net/qq_21310939/article/details/107401400