SpringBoot?spring.factories加載時機分析
spring.factories作用
這個類似于Java中的SPI功能,SpringBoot啟動的時候會讀取所有jar包下面的META-INF/spring.factories
文件;
并且將文件中的 接口/抽象類 對應的實現(xiàn)類都對應起來,并在需要的時候可以實例化對應的實現(xiàn)類
下面我們來分析一下源碼看看spring.factories
的使用場景
源碼解析
啟動SpringApplication,看看構造方法
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中指定類實例用的;并且獲取的時候是根據(jù)讀取整個項目中文件路徑為META-INF/spring.factories
中的內容實例化對應的實例類的;
例如這里的ApplicationContextInitializer
是一個接口,那么應該實例化哪些他的實現(xiàn)類呢?那就找META-INF/spring.factories
文件 ; 那么我們在spring-boot:2.1.0
jar包中找到了這個文件
讀取到需要實例化的實現(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
中找到了這個文件
那么文件中的兩個實現(xiàn)類也會被實例化;加上上面4個總共有6個
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\ org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
可以看到不僅僅只是把org.springframework.context.ApplicationContextInitializer
的實例類解析了出來;而是所有的都解析了出來并且保存下來了.下次其他的類需要被實例化的時候就可以直接從內存里面拿了;
上面過程拿到了實例類之后,接下來就是實例化的過程了
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) { ClassLoader classLoader = getClassLoader(); // Use names and ensure unique to protect against duplicates Set<String> names = new LinkedHashSet<>( SpringFactoriesLoader.loadFactoryNames(type, classLoader)); List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); AnnotationAwareOrderComparator.sort(instances); return instances; }
方法createSpringFactoriesInstances
就是創(chuàng)建實例的過程;可以看到傳入了對應的接口類org.springframework.context.ApplicationContextInitializer
;接下來就會實例化 上面找到了對應的實現(xiàn)類;
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args, Set<String> names) { List<T> 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; }
實例化的過程如果,沒有什么特別需要講解的;
上面有個方法 AnnotationAwareOrderComparator.sort(instances);
是用來排序所有實例的; 實現(xiàn)類需要實現(xiàn) 接口Ordered
; getOrder返回的值越小,優(yōu)先級更高
用法
知道spring.factories
的用法之后, 那么我們就可以利用這個特性實現(xiàn)自己的目的;
例如我們也可以寫一個接口類ApplicationContextInitializer
的實現(xiàn)類;
等等之類的;
以上就是SpringBoot spring.factories加載時機分析的詳細內容,更多關于spring.factories加載時機的資料請關注腳本之家其它相關文章!
- Spring中的spring.factories文件用法(Spring如何加載第三方Bean)
- springboot自動配置原理以及spring.factories文件的作用詳解
- springboot 加載 META-INF/spring.factories方式
- SpringBoot借助spring.factories文件跨模塊實例化Bean
- 關于SpringBoot3.x中spring.factories功能被移除的解決方案
- springBoot?之spring.factories擴展機制示例解析
- SpringBoot 自動掃描第三方包及spring.factories失效的問題解決
- SpringBoot3.x中spring.factories?SPI?服務發(fā)現(xiàn)機制的改變問題小結
- SpringBoot之spring.factories的使用方式
- 在SpringBoot3中spring.factories配置不起作用的原因和解決方法
- 淺談spring.factories文件的作用
相關文章
java 下執(zhí)行mysql 批量插入的幾種方法及用時
java 下執(zhí)行mysql 批量插入的幾種方法及用時,1000次插入方法的比較。2013-04-04spring boot 開發(fā)soap webservice的實現(xiàn)代碼
這篇文章主要介紹了spring boot 開發(fā)soap webservice的實現(xiàn)代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-01-01Java設計模式之代理模式_動力節(jié)點Java學院整理
這篇文章主要介紹了Java設計模式之代理模式,本文詳細的介紹了什么事代理模式和相關的類和接口,有興趣的可以了解一下2017-08-08詳解利用Spring的AbstractRoutingDataSource解決多數(shù)據(jù)源的問題
本篇文章主要介紹了詳解利用Spring的AbstractRoutingDataSource解決多數(shù)據(jù)源的問題。具有一定的參考價值,有興趣的可以了解一下。2017-03-03