圖文并茂,Spring Boot Starter 萬字詳解!還有誰不會(huì)?
點(diǎn)擊上方“碼農(nóng)突圍”,馬上關(guān)注
這里是碼農(nóng)充電第一站,回復(fù)“666”,獲取一份專屬大禮包 真愛,請(qǐng)?jiān)O(shè)置“星標(biāo)”或點(diǎn)個(gè)“在看

1.1 什么是starter(場景啟動(dòng)器)
首先項(xiàng)目中需要引入SpringMVC的依賴 在web.xml中注冊(cè)SpringMVC的 DispatcherServlet,并配置url映射編寫 springmcv-servlet.xml,在其中配置SpringMVC中幾個(gè)重要的組件,處理映射器(HandlerMapping)、處理適配器(HandlerAdapter)、視圖解析器(ViewResolver)在 applicationcontext.xml文件中引入springmvc-servlet.xml文件…
依賴導(dǎo)入問題: 每個(gè)項(xiàng)目都需要來單獨(dú)維護(hù)自己所依賴的jar包,在項(xiàng)目中使用到什么功能就需要引入什么樣的依賴。手動(dòng)導(dǎo)入依賴容易出錯(cuò),且無法統(tǒng)一集中管理 配置繁瑣: 在引入依賴之后需要做繁雜的配置,并且這些配置是每個(gè)項(xiàng)目來說都是必要的,例如web.xml配置(Listener配置、Filter配置、Servlet配置)、log4j配置、數(shù)據(jù)庫連接池配置等等。這些配置重復(fù)且繁雜,在不同的項(xiàng)目中需要進(jìn)行多次重復(fù)開發(fā),這在很大程度上降低了我們的開發(fā)效率
二、SpringBoot場景啟動(dòng)器的原理
相關(guān)組件的自動(dòng)導(dǎo)入 相關(guān)組件的自動(dòng)配置
2.1 自動(dòng)配置原理
2.1.1 自動(dòng)配置類的獲取與注入
@SpringBootApplication //標(biāo)注這個(gè)類是一個(gè)springboot的應(yīng)用
public class CommunityApplication {
public static void main(String[] args) {
//將springboot應(yīng)用啟動(dòng)
SpringApplication.run(CommunityApplication.class, args);
}
}
@SpringBootApplication注解內(nèi)部結(jié)構(gòu)如下圖所示:
AutoConfigurationImportSelector :重點(diǎn)看該類中重寫的selectImports方法,看下它返回的字符串?dāng)?shù)組是如何得來的:
spring.factories文件中去看一下,找到spring官方提供的spring-boot-autoconfigure包,在其下去找一下該文件:
@Bean注解向容器中注入了一些Bean
SpringBoot在啟動(dòng)的時(shí)候從類路徑下的 META-INF/spring.factories中獲取EnableAutoConfiguration指定的所有自動(dòng)配置類的全限定類名將這些自動(dòng)配置類導(dǎo)入容器,自動(dòng)配置類就生效,幫我們進(jìn)行自動(dòng)配置工作; 整個(gè)J2EE的整體解決方案和自動(dòng)配置都在 spring-boot-autoconfigure的jar包中;它會(huì)給容器中導(dǎo)入非常多的自動(dòng)配置類 (xxxAutoConfiguration), 就是給容器中導(dǎo)入這個(gè)場景需要的所有組件,并配置好這些組件 ; 有了自動(dòng)配置類,免去了我們手動(dòng)編寫配置注入功能組件等的工作;
2.1.2 自動(dòng)配置的過程
@ConfigurationProperties注解來與我們程序內(nèi)部定義的POJO類來產(chǎn)生關(guān)聯(lián),這些POJO類統(tǒng)一命名為xxxProperties,并且這些xxxProperties類中各個(gè)屬性字段都有自己的默認(rèn)值,這也是SpringBoot約定大于配置理念的體現(xiàn),盡可能減少用戶做選擇的次數(shù),但同時(shí)又不失靈活性。只要我們想,配置文件中的配置隨時(shí)可以覆蓋默認(rèn)值。
@EnableConfigurationProperties注解,就可以自動(dòng)將與配置文件綁定好的這個(gè)類注入到容器中供我們使用。根據(jù)限定的條件向容器中注入組件 使用xxxProperties對(duì)注入的組件的相關(guān)屬性進(jìn)行配置
//表示這是一個(gè)配置類,和以前編寫的配置文件一樣,也可以給容器中添加組件;
@Configuration
//將與配置文件綁定好的某個(gè)類注入到容器中,使其生效
//進(jìn)入這個(gè)HttpProperties查看,將配置文件中對(duì)應(yīng)的值和HttpProperties綁定起來;
//并把HttpProperties加入到ioc容器中
@EnableConfigurationProperties(HttpProperties.class)
//Spring底層@Conditional注解
//根據(jù)不同的條件判斷,如果滿足指定的條件,整個(gè)配置類里面的配置就會(huì)生效;
//這里的意思就是判斷當(dāng)前應(yīng)用是否是web應(yīng)用,如果是,當(dāng)前配置類生效
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
//判斷系統(tǒng)中有沒有CharacterEncodingFilter這個(gè)類,如果有配置類才生效
@ConditionalOnClass(CharacterEncodingFilter.class)
//判斷配置文件中是否存在某個(gè)配置:spring.http.encoding.enabled;
//matchIfMissing = true表明即使我們配置文件中不配置pring.http.encoding.enabled=true,該配置類也是默認(rèn)生效的;
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {
//該類已經(jīng)與配置文件綁定了
private final HttpProperties.Encoding properties;
//構(gòu)建該自動(dòng)配置類時(shí)將與配置文件綁定的配置類作為入?yún)鬟f進(jìn)去
public HttpEncodingAutoConfiguration(HttpProperties properties) {
this.properties = properties.getEncoding();
}
@Bean
@ConditionalOnMissingBean
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.properties.getCharset().name()); //注入bean時(shí)使用配置類中屬性的值進(jìn)行初始化,相當(dāng)于將配置文件中的值映射到了組件的某些屬性上
filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
return filter; //注入配置好的bean
}
}
首先容器會(huì)根據(jù)當(dāng)前不同的條件判斷,決定這個(gè)配置類是否生效! 一但這個(gè)配置類生效;這個(gè)配置類就會(huì)給容器中添加相應(yīng)組件; 這些組件的屬性是從對(duì)應(yīng)的properties類中獲取的,這些類里面的每一個(gè)屬性又是和配置文件綁定的; 所有在配置文件中能配置的屬性都是在xxxxProperties類中封裝著,配置文件可以配置什么內(nèi)容,可以參照該前綴對(duì)應(yīng)的屬性類中的屬性字段
//從配置文件中獲取指定的值和bean的屬性進(jìn)行綁定
@ConfigurationProperties(prefix = "spring.http")
public class HttpProperties {
// .....
}
2.2 SpringBoot自動(dòng)配置使用總結(jié)
SpringBoot啟動(dòng)會(huì)加載大量的自動(dòng)配置類 我們首先可以看我們需要的功能有沒有在SpringBoot默認(rèn)寫好的自動(dòng)配置類當(dāng)中; 我們?cè)賮砜催@個(gè)自動(dòng)配置類中到底配置了哪些組件;(只要我們要用的組件存在在其中,我們就不需要再手動(dòng)配置了) 給容器中自動(dòng)配置類添加組件的時(shí)候,會(huì)從properties類中獲取某些屬性。我們只需要在配置文件中指定這些屬性的值即可; xxxxAutoConfigurartion:自動(dòng)配置類;給容器中添加組件xxxxProperties:封裝配置文件中相關(guān)屬性;
@Conditional派生注解(Spring注解版原生的@Conditional作用)@Conditional指定的條件成立,才給容器中添加組件,配置里面的所有內(nèi)容才生效;
debug=true屬性;來讓控制臺(tái)打印自動(dòng)配置報(bào)告,這樣我們就可以很方便的知道哪些自動(dòng)配置類生效;#在配置文件中開啟springboot的調(diào)試類
debug=true
Positive matches:(自動(dòng)配置類啟用的:正匹配)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:(沒有啟動(dòng),沒有匹配成功的自動(dòng)配置類:負(fù)匹配)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:
-----------
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
三、自定義場景啟動(dòng)器
3.1 starter的命名規(guī)范
前綴: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模塊整體結(jié)構(gòu)
xxxAutoConfiguration:自動(dòng)配置類,對(duì)某個(gè)場景下需要使用到的一些組件進(jìn)行自動(dòng)注入,并利用xxxProperties類來進(jìn)行組件相關(guān)配置xxxProperties:某個(gè)場景下所有可配置屬性的集成,在配置文件中配置可以進(jìn)行屬性值的覆蓋
按照SpringBoot官方的定義,Starer的作用就是依賴聚合,因此直接在starter內(nèi)部去進(jìn)行代碼實(shí)現(xiàn)是不符合規(guī)定的,starter應(yīng)該只起到依賴導(dǎo)入的作用,而具體的代碼實(shí)現(xiàn)應(yīng)該去交給其他模塊來實(shí)現(xiàn),然后在starter中去引用該模塊即可,因此整體的starter的構(gòu)成應(yīng)該如下圖所示:
xxxAutoConfiguration與xxxProperties的具體實(shí)現(xiàn),都封裝在自動(dòng)配置模塊中,starter實(shí)際是通過該模塊來對(duì)外提供相應(yīng)的功能。3.3 autoconfigure模塊開發(fā)
3.3.1 依賴引入
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<!-- 包含很多與自動(dòng)配置相關(guān)的注解的定義,必須要引入 -->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<!-- 非必須的,引入后可以在配置文件中輸入我們自定義配置的時(shí)候有相應(yīng)的提示,也可以通過其他.properties文件為相關(guān)類進(jìn)行屬性映射(SpringBoot默認(rèn)使用application.yml)-->
<optional>true</optional>
</dependency>
<dependencies>
3.3.2 xxxAutoConfiguration的實(shí)現(xiàn)
@Configuration
@ConditionalOnxxx
@ConditionalOnxxx//限定自動(dòng)配置類生效的一些條件
@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的實(shí)現(xiàn)
@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文件
spring.factories文件,并添加寫好的xxxAutoConfiguration類:org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.meituan.xframe.boot.mcc.autoconfigure.xxxAutoConfiguration
3.4 Starter模塊開發(fā)
<dependencies>
================================================================
<!--添加了對(duì)autoconfigure模塊的引用-->
<dependency>
<groupId>com.test.starter</groupId>
<artifactId>xxx-spring-boot-autoconfigure</artifactId>
</dependency>
===============================================================
<!--其他的一些必要依賴項(xiàng)-->
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
</dependency>
</dependencies>
-End-
最近有一些小伙伴,讓我?guī)兔φ乙恍?nbsp;面試題 資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來,可以說是程序員面試必備!所有資料都整理到網(wǎng)盤了,歡迎下載!
點(diǎn)擊??卡片,關(guān)注后回復(fù)【面試題】即可獲取
評(píng)論
圖片
表情

