springBoot?之spring.factories擴(kuò)展機(jī)制示例解析
引言
這個(gè)月準(zhǔn)備寫完Spring源碼解析系列文章。我相信大多點(diǎn)進(jìn)來看的同學(xué)們都應(yīng)該或多或少對(duì)springBoot的擴(kuò)展機(jī)制有一些了解,我們這次通過八股文歸納法和源碼淺層解析,達(dá)到大家對(duì)SpringBoot擴(kuò)展的機(jī)制的理解。全文看完大概三分鐘,希望大家都有收獲,畢竟藝多不壓身,知其然知其所以然。
在Spring Boot中,我們通常會(huì)看到一些源碼包的META-INF下又一個(gè)文件spring.factories
。大家都知道它是一種擴(kuò)展機(jī)制,有的同學(xué)可能在其他博客中看到把它稱之為Spring Boot SPI
。為什么這么稱謂呢,后續(xù)我專門分享一篇Java SPI。那么到底它是如何實(shí)現(xiàn)spring Boot的擴(kuò)展的呢。在本文中,我們將深入探討這種擴(kuò)展機(jī)制的底層源代碼實(shí)現(xiàn),以及我們?cè)谠创a上標(biāo)注注釋的形式,共同揭開Spring.factories 的神秘面紗。
1. spring.factories八股總結(jié)
如果只是需要應(yīng)付面試或者只是想大概了解,看完此章節(jié)就可以了
1.1 spring.factories文件格式
在分析spring.factories的底層實(shí)現(xiàn)之前,我們需要了解spring.factories文件的格式。spring.factories文件是一個(gè)標(biāo)準(zhǔn)的Properties文件,其中鍵是要擴(kuò)展的類型的全限定名,值是要注冊(cè)的bean的全限定名。
例如
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.MyAutoConfiguration。
1.2 SpringFactoriesLoader類
SpringFactoriesLoader是一個(gè)實(shí)用類,它用于加載spring.factories文件并注冊(cè)bean定義。以下是SpringFactoriesLoader類的源代碼: loadFactory方法首先使用傳遞的Class對(duì)象的名稱作為鍵調(diào)用loadFactories方法來獲取已注冊(cè)bean的全限定名列表。然后,它使用Java 8的Stream API將全限定名列表映射到相應(yīng)的Class對(duì)象,并使用反射通過無參數(shù)構(gòu)造函數(shù)實(shí)例化每個(gè)Class對(duì)象。最后,它將實(shí)例化的對(duì)象收集到一個(gè)List對(duì)象中并返回。
1.3 loadFactories方法
loadFactories方法是SpringFactoriesLoader類的私有方法,它接收一個(gè)要擴(kuò)展的類型的Class對(duì)象和一個(gè)ClassLoader對(duì)象,并返回一個(gè)包含所有已注冊(cè)bean的List對(duì)象loadFactories方法首先使用傳遞的Class對(duì)象的名稱作為鍵從緩存Map中獲取已注冊(cè)bean的全限定名列表。
如果緩存中沒有,則使用傳遞的ClassLoader對(duì)象從classpath中獲取所有spring.factories文件的URL,并使用PropertiesLoaderUtils類加載每個(gè)文件中的Properties對(duì)象。
對(duì)于每個(gè)Properties對(duì)象,它獲取與傳遞的Class對(duì)象的名稱相對(duì)應(yīng)的屬性值, 在Spring Boot中,spring.factories
是一個(gè)非常重要的配置文件,它用于實(shí)現(xiàn)Spring Boot的自動(dòng)化配置。這個(gè)文件位于META-INF/spring.factories
路徑下,通??梢栽陧?xiàng)目的classpath下找到。
spring.factories
文件的格式如下所示:
# Auto Configuration org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.MyAutoConfiguration
這個(gè)文件中定義了一個(gè)名為org.springframework.boot.autoconfigure.EnableAutoConfiguration
的屬性,它的值是一個(gè)類的完全限定名,即com.example.MyAutoConfiguration
。這個(gè)類通常是一個(gè)Spring配置類,用于定義一些自動(dòng)化配置。
Spring Boot在啟動(dòng)時(shí)會(huì)掃描classpath中的所有spring.factories
文件,并讀取其中定義的屬性。然后,它會(huì)根據(jù)這些屬性值加載對(duì)應(yīng)的類,并將它們注冊(cè)到Spring的ApplicationContext中。
好吧,如上所示是Spring Boot中spring.factories
的底層源碼解析: 整個(gè)加載過程我們可以大致分為5步
.
你也可以理解為咱們整理的為了方便記憶八股文吧
- Spring Boot通過
SpringFactoriesLoader
類來加載spring.factories
文件。這個(gè)類是Spring框架中的一個(gè)工具類,用于加載classpath下的所有spring.factories
文件,并將它們的內(nèi)容存儲(chǔ)在一個(gè)Map<String, List<String>>
對(duì)象中。 - Spring Boot使用
SpringFactoriesLoader.loadFactoryNames
方法來加載指定屬性名的所有實(shí)現(xiàn)類。這個(gè)方法會(huì)從步驟1中加載的Map<String, List<String>>
對(duì)象中獲取對(duì)應(yīng)屬性名的實(shí)現(xiàn)類列表。 - Spring Boot使用
SpringFactoriesLoader.loadFactories
方法來加載指定屬性名的所有實(shí)現(xiàn)類的實(shí)例。這個(gè)方法會(huì)遍歷步驟2中獲取的實(shí)現(xiàn)類列表,并使用反射機(jī)制實(shí)例化每一個(gè)類。 - Spring Boot會(huì)將步驟3中實(shí)例化的類注冊(cè)為Spring的Bean。它會(huì)調(diào)用
AnnotationConfigUtils.registerAnnotationConfigProcessors
方法來注冊(cè)自動(dòng)配置類。這個(gè)方法會(huì)調(diào)用BeanDefinitionRegistryPostProcessor
接口的實(shí)現(xiàn)類的postProcessBeanDefinitionRegistry
方法,來注冊(cè)自動(dòng)配置類的BeanDefinition。 - Spring Boot會(huì)啟動(dòng)Spring的ApplicationContext,并讓它自動(dòng)掃描所有的Bean。它會(huì)調(diào)用
AnnotationConfigApplicationContext.refresh
方法來啟動(dòng)ApplicationContext,并讓它自動(dòng)掃描所有的Bean。在掃描過程中,Spring會(huì)發(fā)現(xiàn)步驟4中注冊(cè)的自動(dòng)配置類,并嘗試自動(dòng)配置應(yīng)用程序。
/** * SpringFactoriesLoader類是Spring框架中的一個(gè)工具類,用于加載classpath下的所有spring.factories文件, * 并將它們的內(nèi)容存儲(chǔ)在一個(gè)Map<String, List<String>>對(duì)象中。 */ public final class SpringFactoriesLoader { /** * 私有構(gòu)造函數(shù),不允許實(shí)例化。 */ private SpringFactoriesLoader() { } /** * 加載指定屬性名的所有實(shí)現(xiàn)類的類名列表。 * @param factoryType 屬性名 * @param classLoader 類加載器 * @return 類名列表 */ public static List<String> loadFactoryNames(Class<?> factoryType, ClassLoader classLoader) { // ... } /** * 加載指定屬性名的所有實(shí)現(xiàn)類的實(shí)例。 * @param factoryType 屬性名 * @param classLoader 類加載器 * @param <T> 實(shí)現(xiàn)類的類型 * @return 實(shí)現(xiàn)類的實(shí)例列表 */ public static <T> List<T> loadFactories(Class<T> factoryType, ClassLoader classLoader) { // 省略 ... } }
/** * AnnotationConfigUtils類提供了一些用于處理注解配置的工具方法。 */ class AnnotationConfigUtils { /** * 注冊(cè)自動(dòng)配置類。 * @param registry Bean定義注冊(cè)器 */ public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) { // ... } }
/** * AnnotationConfigApplicationContext類是Spring的ApplicationContext接口的一個(gè)實(shí)現(xiàn)類, * 用于支持基于Java配置的應(yīng)用程序上下文。 */ public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry { /** * 啟動(dòng)ApplicationContext,并讓它自動(dòng)掃描所有的Bean。 */ @Override public void refresh() throws BeansException, IllegalStateException { // ... } }
好了,今天的內(nèi)容就到這兒了,每天寫點(diǎn)東西整理和總結(jié)。謝謝大家的閱讀。放棄很容易但堅(jiān)持一定很酷。一起加油
更多關(guān)于springBoot spring.factories擴(kuò)展的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Spring中的spring.factories文件用法(Spring如何加載第三方Bean)
- springboot自動(dòng)配置原理以及spring.factories文件的作用詳解
- springboot 加載 META-INF/spring.factories方式
- SpringBoot借助spring.factories文件跨模塊實(shí)例化Bean
- 關(guān)于SpringBoot3.x中spring.factories功能被移除的解決方案
- SpringBoot?spring.factories加載時(shí)機(jī)分析
- SpringBoot 自動(dòng)掃描第三方包及spring.factories失效的問題解決
- SpringBoot3.x中spring.factories?SPI?服務(wù)發(fā)現(xiàn)機(jī)制的改變問題小結(jié)
- SpringBoot之spring.factories的使用方式
- 在SpringBoot3中spring.factories配置不起作用的原因和解決方法
- 淺談spring.factories文件的作用
相關(guān)文章
jquery uploadify和apache Fileupload實(shí)現(xiàn)異步上傳文件示例
這篇文章主要介紹了jquery uploadify和apache Fileupload實(shí)現(xiàn)異步上傳文件示例,需要的朋友可以參考下2014-05-05Java網(wǎng)絡(luò)編程UDP實(shí)現(xiàn)多線程在線聊天
這篇文章主要為大家詳細(xì)介紹了Java網(wǎng)絡(luò)編程UDP實(shí)現(xiàn)多線程在線聊天,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07Spark調(diào)優(yōu)多線程并行處理任務(wù)實(shí)現(xiàn)方式
這篇文章主要介紹了Spark調(diào)優(yōu)多線程并行處理任務(wù)實(shí)現(xiàn)方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08Java Socket編程實(shí)現(xiàn)簡(jiǎn)單的問候服務(wù)
這篇文章主要為大家介紹了Java Socket編程實(shí)現(xiàn)簡(jiǎn)單的問候服務(wù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-01-01Spring Boot 如何將 Word 轉(zhuǎn)換為 PDF
這篇文章主要介紹了Spring Boot將Word轉(zhuǎn)換為 PDF,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-08-08RabbitMQ消費(fèi)端ACK NACK及重回隊(duì)列機(jī)制詳解
這篇文章主要為大家介紹了RabbitMQ消費(fèi)端ACK NACK及重回隊(duì)列機(jī)制詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12一文教你掌握J(rèn)ava如何實(shí)現(xiàn)判空
實(shí)際項(xiàng)目中我們會(huì)有很多地方需要判空校驗(yàn),如果不做判空校驗(yàn)則可能產(chǎn)生NullPointerException異常。所以本文小編為大家整理了Java中幾個(gè)常見的判空方法,希望對(duì)大家有所幫助2023-04-04