SpringBoot?spring.factories加載時(shí)機(jī)分析_今日熱搜
時(shí)間:2023-06-24 16:49:46
目錄
spring.factories作用源碼解析用法spring.factories作用
這個(gè)類似于Java中的SPI功能,SpringBoot啟動(dòng)的時(shí)候會(huì)讀取所有jar包下面的META-INF/spring.factories文件;
并且將文件中的 接口/抽象類 對(duì)應(yīng)的實(shí)現(xiàn)類都對(duì)應(yīng)起來(lái),并在需要的時(shí)候可以實(shí)例化對(duì)應(yīng)的實(shí)現(xiàn)類
下面我們來(lái)分析一下源碼看看spring.factories的使用場(chǎng)景
(相關(guān)資料圖)
源碼解析
啟動(dòng)SpringApplication,看看構(gòu)造方法
public SpringApplication(ResourceLoader resourceLoader, Class>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
其中方法getSpringFactoriesInstances( ApplicationContextInitializer.class)是用于獲取Spring中指定類實(shí)例用的;并且獲取的時(shí)候是根據(jù)讀取整個(gè)項(xiàng)目中文件路徑為META-INF/spring.factories中的內(nèi)容實(shí)例化對(duì)應(yīng)的實(shí)例類的;
例如這里的ApplicationContextInitializer是一個(gè)接口,那么應(yīng)該實(shí)例化哪些他的實(shí)現(xiàn)類呢?那就找META-INF/spring.factories文件 ; 那么我們?cè)?code>spring-boot:2.1.0jar包中找到了這個(gè)文件
讀取到需要實(shí)例化的實(shí)現(xiàn)類為
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\ org.springframework.boot.context.ContextIdApplicationContextInitializer,\ org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\ org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
并且還在spring-boot-autoconfigure-2.1.0.RELEASE.jar中找到了這個(gè)文件
那么文件中的兩個(gè)實(shí)現(xiàn)類也會(huì)被實(shí)例化;加上上面4個(gè)總共有6個(gè)
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\ org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
可以看到不僅僅只是把org.springframework.context.ApplicationContextInitializer 的實(shí)例類解析了出來(lái);而是所有的都解析了出來(lái)并且保存下來(lái)了.下次其他的類需要被實(shí)例化的時(shí)候就可以直接從內(nèi)存里面拿了;
上面過(guò)程拿到了實(shí)例類之后,接下來(lái)就是實(shí)例化的過(guò)程了
privateCollection getSpringFactoriesInstances(Class type, Class>[] parameterTypes, Object... args) { ClassLoader classLoader = getClassLoader(); // Use names and ensure unique to protect against duplicates Set names = new LinkedHashSet<>( SpringFactoriesLoader.loadFactoryNames(type, classLoader)); List instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); AnnotationAwareOrderComparator.sort(instances); return instances; }
方法createSpringFactoriesInstances就是創(chuàng)建實(shí)例的過(guò)程;可以看到傳入了對(duì)應(yīng)的接口類org.springframework.context.ApplicationContextInitializer ;接下來(lái)就會(huì)實(shí)例化 上面找到了對(duì)應(yīng)的實(shí)現(xiàn)類;
privateList createSpringFactoriesInstances(Class type, Class>[] parameterTypes, ClassLoader classLoader, Object[] args, Set names) { List instances = new ArrayList<>(names.size()); for (String name : names) { try { Class> instanceClass = ClassUtils.forName(name, classLoader); Assert.isAssignable(type, instanceClass); Constructor> constructor = instanceClass .getDeclaredConstructor(parameterTypes); T instance = (T) BeanUtils.instantiateClass(constructor, args); instances.add(instance); } catch (Throwable ex) { throw new IllegalArgumentException( "Cannot instantiate " + type + " : " + name, ex); } } return instances; }
實(shí)例化的過(guò)程如果,沒(méi)有什么特別需要講解的;
上面有個(gè)方法AnnotationAwareOrderComparator.sort(instances);是用來(lái)排序所有實(shí)例的; 實(shí)現(xiàn)類需要實(shí)現(xiàn) 接口Ordered; getOrder返回的值越小,優(yōu)先級(jí)更高
用法
知道spring.factories的用法之后, 那么我們就可以利用這個(gè)特性實(shí)現(xiàn)自己的目的;
例如我們也可以寫一個(gè)接口類ApplicationContextInitializer的實(shí)現(xiàn)類;
等等之類的;
以上就是SpringBoot spring.factories加載時(shí)機(jī)分析的詳細(xì)內(nèi)容,更多關(guān)于spring.factories加載時(shí)機(jī)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)稿件
SpringBoot?spring.factories加載時(shí)機(jī)分析_今日熱搜
白宮:正密切關(guān)注俄羅斯局勢(shì),拜登已聽(tīng)取簡(jiǎn)報(bào) 每日簡(jiǎn)訊
測(cè)運(yùn)勢(shì)2022年運(yùn)勢(shì)免費(fèi),紫微免費(fèi)算2022年運(yùn)勢(shì)|環(huán)球觀察
當(dāng)前要聞:推動(dòng)品牌建設(shè)上臺(tái)階
新資訊:關(guān)系戶來(lái)了?勇士新秀的經(jīng)紀(jì)人竟然是勇士總經(jīng)理的親弟弟?
享譽(yù):哈爾濱專業(yè)治療疤痕醫(yī)院排名[大膽公開]哈爾濱哪家醫(yī)院無(wú)痕祛疤好|當(dāng)前消息
強(qiáng)化審判能力建設(shè) 延伸司法保障職能 ——新疆知識(shí)產(chǎn)權(quán)保護(hù)水平穩(wěn)步提升 天天精選
美國(guó)“里根”號(hào)航母將??吭侥细劭?,越方稱“正常友好交流”
浙江科技學(xué)院怎么樣 浙江科技學(xué)院地址是什么
《星空》浪漫關(guān)系新細(xì)節(jié):可"拋棄"同伴 獨(dú)立單身
【短訊】“瓦格納”首領(lǐng)稱其部隊(duì)已進(jìn)入俄境內(nèi)!一文梳理這場(chǎng)“叛亂”經(jīng)過(guò)……
中國(guó)經(jīng)濟(jì)中長(zhǎng)期前景POLL(2023年5月/PB):經(jīng)濟(jì)、政策雙平穩(wěn)成新主流預(yù)期
環(huán)球新動(dòng)態(tài):南京市醫(yī)保局用新思想指引南京醫(yī)保新實(shí)踐
今冬投運(yùn)!海陽(yáng)至乳山核能供熱工程最新進(jìn)展來(lái)了 每日快訊
【世界播資訊】年銷粽子600萬(wàn)個(gè)!古老“粽子村”里的變與不變
范丞丞的“自私”,讓觀眾看清白鹿的為人,《跑男》因此話題出圈 每日視點(diǎn)
世界熱資訊!移動(dòng)硬盤格式化后能恢復(fù)數(shù)據(jù)嗎(請(qǐng)將磁盤插入可移動(dòng)磁盤)
古裝廠牌到全能玩家,年均爆款的西嘻影業(yè)提供了影視公司的生存法
民營(yíng)企業(yè)法律風(fēng)險(xiǎn)防控提示書怎樣規(guī)定?


