最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot Starter的用法以及原理小結(jié)

 更新時(shí)間:2026年03月02日 09:54:21   作者:Nyarlathotep0113  
本文介紹了如何創(chuàng)建一個(gè)Spring Boot Starter項(xiàng)目,包括創(chuàng)建父模塊、子模塊以及自動(dòng)配置類的編寫,通過(guò)這種方式,可以將功能模塊化,并實(shí)現(xiàn)自動(dòng)裝配,下面就來(lái)具體介紹一下

為了理解SpringBoot Starter的寫法,以hello-spring-boot-starter作為示例來(lái)講解

創(chuàng)建父模塊hello-spring-boot-starter-project

hello-spring-boot-starter-project將作為整個(gè)項(xiàng)目的父模塊,其pom.xml文件如下:

<!--添加子模塊-->  
<modules>  
<module>hello-spring-boot-starter</module>  
<module>hello-spring-boot-starter-autoconfigure</module>  
</modules>  
<!--定義的參數(shù)-->  
<properties>  
<maven.compiler.source>17</maven.compiler.source>  
<maven.compiler.target>17</maven.compiler.target>  
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
<spring-boot.version>3.0.7</spring-boot.version>  
</properties>  
<!--依賴的配置約定-->  
<dependencyManagement>  
<dependencies>  
<dependency>  
<groupId>org.springframework.boot</groupId>  
<artifactId>spring-boot-autoconfigure</artifactId>  
<version>${spring-boot.version}</version>  
</dependency>  
<dependency>  
<groupId>org.springframework.boot</groupId>  
<artifactId>spring-boot-configuration-processor</artifactId>  
<version>3.5.11</version>  
</dependency>  
</dependencies>  
</dependencyManagement> 

創(chuàng)建子模塊hello-spring-boot-starter-autoconfigure

hello-spring-boot-starter-autoconfigure作為父模塊hello-spring-boot-starter-project的一個(gè)子模塊,其pom.xml關(guān)鍵配置如下:

<!--設(shè)置父模塊-->  
<parent>  
<groupId>edu.whut</groupId>  
<artifactId>hello-spring-boot-starter-project</artifactId>  
<version>1.0-SNAPSHOT</version>  
</parent>
<dependencies>  
<dependency>  
<groupId>org.springframework.boot</groupId>  
<artifactId>spring-boot-autoconfigure</artifactId>  
</dependency>  
<dependency>  
<groupId>org.springframework.boot</groupId>  
<artifactId>spring-boot-configuration-processor</artifactId>  
</dependency>  
</dependencies>

在其模塊內(nèi)部創(chuàng)建三個(gè)文件
HelloService.java:

public class HelloService {  
private final HelloProperties properties;  
  
public HelloService(HelloProperties properties) {  
this.properties = properties;  
}  
  
public void sayHello() {  
System.out.println("Hello,"+properties.getObject());  
}  
}

HelloProperties.java:

@ConfigurationProperties(prefix = "hello")  
public class HelloProperties {  
private String object;  
  
public String getObject() {  
return object;  
}  
  
public void setObject(String object) {  
this.object = object;  
}  
}

HelloAutoConfiguration.java:

//標(biāo)識(shí)自動(dòng)配置類  
@AutoConfiguration  
@EnableConfigurationProperties(HelloProperties.class)  
public class HelloAutoConfiguration {  
@Bean  
//在application文件中配置了hello.object配置才會(huì)構(gòu)造這個(gè)bean  
@ConditionalOnProperty(prefix = "hello", name = "object")  
public HelloService helloService(HelloProperties properties) {  
return new HelloService(properties);  
}  
}

hello-spring-boot-starter-autoconfigure模塊中的resources下的META-INF下的spring目錄下創(chuàng)建一個(gè)名為org.springframework.boot.autoconfigure.AutoConfiguration.imports的文件,文件中寫入:

edu.whut.HelloAutoConfiguration

創(chuàng)建hello-spring-boot-starter子模塊

hello-spring-boot-starter作為父模塊hello-spring-boot-starter-project的一個(gè)子模塊,其pom.xml關(guān)鍵配置如下:

<!--指定父模塊-->  
<parent>  
<groupId>edu.whut</groupId>  
<artifactId>hello-spring-boot-starter-project</artifactId>  
<version>1.0-SNAPSHOT</version>  
</parent>
<dependencies>  
<dependency>  
<groupId>edu.whut</groupId>  
<artifactId>hello-spring-boot-starter-autoconfigure</artifactId>  
<version>1.0-SNAPSHOT</version>  
</dependency>  
</dependencies>

這樣這個(gè)模塊就完成了

使用hello-spring-boot-starter

隨意創(chuàng)建一個(gè)springboot項(xiàng)目,在main方法中查找對(duì)應(yīng)的名為helloServicebean

public static void main(String[] args) {  
ConfigurableApplicationContext applicationContext = SpringApplication.run(DemoApplication.class, args);  
Object bean = applicationContext.getBean("helloService");  
System.out.println(bean);  
}

結(jié)果為:

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'helloService' available
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:978)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1381)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1296)
    at com.example.demo.DemoApplication.main(DemoApplication.java:12)

這是正常的,因?yàn)楝F(xiàn)在還未設(shè)置配置,更改aplication.properties,寫入:

hello.object="world"

再次運(yùn)行程序,現(xiàn)在就可以獲取到starter中配置的bean

edu.whut.HelloService@4463d9d3

為什么要使用springboot starter?

有人可能好奇,這么大費(fèi)周章,就是為了把一個(gè)對(duì)象注入到IOC容器中?那為什么不直接在項(xiàng)目里注入?
因?yàn)槊總€(gè)Starter是一個(gè)高內(nèi)聚的功能模塊,通過(guò)依賴傳遞條件化配置@ConditionalOnClass等)實(shí)現(xiàn)“智能裝配”,避免冗余代碼。

為什么不直接寫starter,反而需要一個(gè)autoconfigure?

這是為了遵循Spring Boot官方提倡的“關(guān)注點(diǎn)分離”原則,將自動(dòng)配置邏輯和依賴管理解耦,讓架構(gòu)更清晰、更易維護(hù)。
autoconfigure包含條件化配置類、@ConfigurationProperties、META-INF/spring.factories(或org.springframework.boot.autoconfigure.AutoConfiguration.imports)

starter僅一個(gè)pom.xml,聚合autoconfigure模塊? + 該功能所需的所有第三方依賴

springboot starter自動(dòng)裝配的原理

@SpringBootApplciation注解是一個(gè)組合注解,這個(gè)注解被一個(gè)@EnableAutoConfiguration所注解。

@EnableAutoConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class) // 核心關(guān)鍵
public @interface EnableAutoConfiguration {
    // ...
}

ImportSelector是一個(gè)用于動(dòng)態(tài)、編程式地選擇要導(dǎo)入的配置類的核心接口,它是一個(gè)函數(shù)式接口,核心方法是:

String[] selectImports(AnnotationMetadata importingClassMetadata);

這個(gè)方法根據(jù)給定的注解元數(shù)據(jù)(被@Import注解的類的信息),返回一個(gè)由全限定類名組成的字符串?dāng)?shù)組。這些返回的類名會(huì)在運(yùn)行時(shí)被Spring容器處理,就像它們?cè)揪捅?code>@Import注解直接引用一樣,其內(nèi)部的@Configuration、@Bean等注解會(huì)被正常解析。

AutoConfigurationImportSelector

AutoConfigurationImportSelector實(shí)現(xiàn)了ImportSelector接口,實(shí)現(xiàn)了selectImports方法。

public String[] selectImports(AnnotationMetadata annotationMetadata) {  
// 1. 檢查是否開啟了自動(dòng)裝配(默認(rèn)是開啟的)
if (!this.isEnabled(annotationMetadata)) {  
return NO_IMPORTS;  
} else {  
AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);  
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());  
}  
}

因此核心的邏輯是getAutoConfigurationEntry(annotationMetadata)

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {  
if (!this.isEnabled(annotationMetadata)) {  
return EMPTY_ENTRY;  
} else {  
AnnotationAttributes attributes = this.getAttributes(annotationMetadata); 
//加載所有候選配置類
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);  //移除重復(fù)和顯式排除的類
configurations = this.removeDuplicates(configurations);  
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);  
this.checkExcludedClasses(configurations, exclusions);  
configurations.removeAll(exclusions);  
//進(jìn)行條件注解的篩選
configurations = this.getConfigurationClassFilter().filter(configurations);  
this.fireAutoConfigurationImportEvents(configurations, exclusions);  
return new AutoConfigurationEntry(configurations, exclusions);  
}  
}

在這個(gè)方法中,核心邏輯只有三步:

  1. 加載所有的候選配置類
  2. 移除重復(fù)和顯式排除的類
  3. 進(jìn)行“條件注解”篩選

加載候選配置類

調(diào)用 getCandidateConfigurations()。這個(gè)方法會(huì)去約定好的位置,讀取一個(gè)文件,這個(gè)文件里列出了所有可能被加載的自動(dòng)配置類。
這個(gè)約定好的位置,在springboot3是META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports,這個(gè)文件的每一行是一個(gè)全類名,在springboot2.x中是META-INF/spring.factories,org.springframework.boot.autoconfigure.EnableAutoConfiguration為鍵的值就是一系列全類名。
無(wú)論哪種格式,此時(shí)得到的都是一個(gè)巨大的List,包含了Spring Boot所有內(nèi)置的(如DataSourceAutoConfiguration, WebMvcAutoConfiguration)以及第三方starter提供的自動(dòng)配置類。因此要進(jìn)行后續(xù)的排除和篩選。

總結(jié)

  1. 啟動(dòng):執(zhí)行SpringApplication.run(),啟動(dòng)Spring容器
  2. 觸發(fā):容器解析主類上的@SpringBootApplication->@EnableAutoConfiguration
  3. 決策:@EnableAutoConfiguration導(dǎo)入AutoConfigurationImportSelector
  4. 掃描:AutoConfigurationImportSelector從 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(Spring Boot 3)中讀取所有候選自動(dòng)配置類。
  5. 排除和篩選:對(duì)候選列表進(jìn)行層層篩選。
  6. 導(dǎo)入:將最終滿足所有條件的自動(dòng)配置類的全限定名數(shù)組返回給容器。
  7. 解析與注冊(cè):容器將這些自動(dòng)配置類當(dāng)作普通的 @Configuration類進(jìn)行解析,將其內(nèi)部符合條件的 @Bean方法注冊(cè)為Bean定義。

到此這篇關(guān)于SpringBoot Starter的用法以及原理小結(jié)的文章就介紹到這了,更多相關(guān)SpringBoot Starter用法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JAVA 區(qū)分集合和數(shù)組

    JAVA 區(qū)分集合和數(shù)組

    這篇文章主要介紹了JAVA如何區(qū)分集合和數(shù)組,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • Java如何根據(jù)前端返回的字段名進(jìn)行查詢數(shù)據(jù)

    Java如何根據(jù)前端返回的字段名進(jìn)行查詢數(shù)據(jù)

    這篇文章主要為大家詳細(xì)介紹了Java如何根據(jù)前端返回的字段名進(jìn)行查詢數(shù)據(jù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-11-11
  • mybatis?plus配置自動(dòng)create_time和update_time方式

    mybatis?plus配置自動(dòng)create_time和update_time方式

    在處理數(shù)據(jù)時(shí),注意時(shí)間類型的轉(zhuǎn)換非常重要,不同編程環(huán)境和數(shù)據(jù)庫(kù)對(duì)時(shí)間數(shù)據(jù)的處理方式各異,因此在數(shù)據(jù)遷移或日常處理中需謹(jǐn)慎處理時(shí)間格式,個(gè)人經(jīng)驗(yàn)表明,了解常用的時(shí)間轉(zhuǎn)換函數(shù)和方法能有效避免錯(cuò)誤,提高工作效率,希望這些經(jīng)驗(yàn)?zāi)転榇蠹規(guī)?lái)幫助
    2024-09-09
  • Java網(wǎng)絡(luò)編程之UDP協(xié)議詳細(xì)解讀

    Java網(wǎng)絡(luò)編程之UDP協(xié)議詳細(xì)解讀

    這篇文章主要介紹了Java網(wǎng)絡(luò)編程之UDP協(xié)議詳細(xì)解讀,UDP協(xié)議全稱是用戶數(shù)據(jù)報(bào)協(xié)議,在網(wǎng)絡(luò)中它與TCP協(xié)議一樣用于處理數(shù)據(jù)包,是一種無(wú)連接的協(xié)議,在OSI模型中,在第四層——傳輸層,處于IP協(xié)議的上一層,需要的朋友可以參考下
    2023-12-12
  • 2021最新IDEA的各種快捷鍵匯總

    2021最新IDEA的各種快捷鍵匯總

    掌握idea的各種快捷鍵,可以幫助我們開發(fā)程序,今天小編給大家?guī)?lái)幾種比較常用的idea快捷鍵及一些快捷鍵介紹,對(duì)idea快捷鍵相關(guān)知識(shí),感興趣的朋友一起看看吧
    2021-05-05
  • SpringBoot bean的多種加載方式示例詳解

    SpringBoot bean的多種加載方式示例詳解

    本文詳細(xì)介紹了在SpringBoot中加載Bean的多種方式,包括通過(guò)xml配置文件、注解定義、特殊方式如FactoryBean、@ImportResource、ApplicationContext以及使用@Import注解導(dǎo)入bean的方法,感興趣的朋友跟隨小編一起看看吧
    2024-10-10
  • mybatis自動(dòng)掃描和自定義類注解方式

    mybatis自動(dòng)掃描和自定義類注解方式

    這篇文章主要介紹了mybatis自動(dòng)掃描和自定義類注解方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • 詳解Java阻塞隊(duì)列(BlockingQueue)的實(shí)現(xiàn)原理

    詳解Java阻塞隊(duì)列(BlockingQueue)的實(shí)現(xiàn)原理

    這篇文章主要介紹了詳解Java阻塞隊(duì)列(BlockingQueue)的實(shí)現(xiàn)原理,阻塞隊(duì)列是Java util.concurrent包下重要的數(shù)據(jù)結(jié)構(gòu),有興趣的可以了解一下
    2017-06-06
  • myeclipse10配置tomcat教程詳解

    myeclipse10配置tomcat教程詳解

    這篇文章主要為大家詳細(xì)介紹了myeclipse10配置tomcat的教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • 解決mybatis竟然報(bào)Invalid value for getInt()的問(wèn)題

    解決mybatis竟然報(bào)Invalid value for getInt()的問(wèn)題

    使用mybatis遇到一個(gè)非常奇葩的問(wèn)題,總是報(bào)Invalid value for getInt()的問(wèn)題,怎么解決呢?下面小編通過(guò)場(chǎng)景分析給大家代來(lái)了mybatis報(bào)Invalid value for getInt()的解決方法,感興趣的朋友參考下吧
    2021-10-10

最新評(píng)論

汝州市| 佛冈县| 车险| 巴林左旗| 通化县| 香格里拉县| 凭祥市| 公主岭市| 绍兴县| 乌兰察布市| 喀喇沁旗| 尉犁县| 丽江市| 绩溪县| 绍兴县| 湄潭县| 濮阳县| 洛浦县| 喜德县| 太仓市| 西林县| 拉孜县| 页游| 天津市| 兰考县| 石城县| 孝感市| 文登市| 富阳市| 常熟市| 蛟河市| 宽城| 仙居县| 阳曲县| 福海县| 息烽县| 信阳市| 金湖县| 临夏县| 南昌市| 海原县|