成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

【源碼透視】SpringBoot的SPI機(jī)制-創(chuàng)新互聯(lián)

一、從java類(lèi)加載機(jī)制說(shuō)起

java中的類(lèi)加載器負(fù)載加載來(lái)自文件系統(tǒng)、網(wǎng)絡(luò)或者其他來(lái)源的類(lèi)文件。jvm的類(lèi)加載器默認(rèn)使用的是雙親委派模式。三種默認(rèn)的類(lèi)加載器Bootstrap ClassLoader、Extension ClassLoader和System ClassLoader(Application ClassLoader)每一個(gè)類(lèi)加載器都確定了從哪些位置加載文件。于此同時(shí)我們也可以通過(guò)繼承java.lang.classloader實(shí)現(xiàn)自己的類(lèi)加載器。

成都創(chuàng)新互聯(lián)是一家從事企業(yè)網(wǎng)站建設(shè)、成都做網(wǎng)站、網(wǎng)站制作、行業(yè)門(mén)戶網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)制作的專(zhuān)業(yè)網(wǎng)站設(shè)計(jì)公司,擁有經(jīng)驗(yàn)豐富的網(wǎng)站建設(shè)工程師和網(wǎng)頁(yè)設(shè)計(jì)人員,具備各種規(guī)模與類(lèi)型網(wǎng)站建設(shè)的實(shí)力,在網(wǎng)站建設(shè)領(lǐng)域樹(shù)立了自己獨(dú)特的設(shè)計(jì)風(fēng)格。自公司成立以來(lái)曾獨(dú)立設(shè)計(jì)制作的站點(diǎn)1000+。
  • Bootstrap ClassLoader:負(fù)責(zé)加載JDK自帶的rt.jar包中的類(lèi)文件,是所有類(lèi)加載的父類(lèi)
  • Extension ClassLoader:負(fù)責(zé)加載java的擴(kuò)展類(lèi)庫(kù)從jre/lib/ect目錄或者java.ext.dirs系統(tǒng)屬性指定的目錄下加載類(lèi),是System ClassLoader的父類(lèi)加載器
  • System ClassLoader:負(fù)責(zé)從classpath環(huán)境變量中加載類(lèi)文件

file

1.1 雙親委派模型

當(dāng)一個(gè)類(lèi)加載器收到類(lèi)加載任務(wù)時(shí),會(huì)先交給自己的父加載器去完成,因此最終加載任務(wù)都會(huì)傳遞到最頂層的BootstrapClassLoader,只有當(dāng)父加載器無(wú)法完成加載任務(wù)時(shí),才會(huì)嘗試自己來(lái)加載。

具體:根據(jù)雙親委派模式,在加載類(lèi)文件的時(shí)候,子類(lèi)加載器首先將加載請(qǐng)求委托給它的父加載器,父加載器會(huì)檢測(cè)自己是否已經(jīng)加載過(guò)類(lèi),如果已經(jīng)加載則加載過(guò)程結(jié)束,如果沒(méi)有加載的話則請(qǐng)求繼續(xù)向上傳遞,直至Bootstrap ClassLoader。如果請(qǐng)求向上委托過(guò)程中,如果始終沒(méi)有檢測(cè)到該類(lèi)已經(jīng)加載,則Bootstrap ClassLoader開(kāi)始嘗試從其對(duì)應(yīng)路勁中加載該類(lèi)文件,如果失敗則由子類(lèi)加載器繼續(xù)嘗試加載,直至發(fā)起加載請(qǐng)求的子加載器為止。

采用雙親委派模式可以保證類(lèi)型加載的安全性,不管是哪個(gè)加載器加載這個(gè)類(lèi),最終都是委托給頂層的BootstrapClassLoader來(lái)加載的,只有父類(lèi)無(wú)法加載時(shí),自己才嘗試加載,這樣就可以保證任何的類(lèi)加載器最終得到的都是同樣一個(gè)Object對(duì)象

protected ClassloadClass(String name, boolean resolve) {synchronized (getClassLoadingLock(name)) {// 首先,檢查該類(lèi)是否已經(jīng)被加載,如果從JVM緩存中找到該類(lèi),則直接返回
    Classc = findLoadedClass(name);
    if (c == null) {try {// 遵循雙親委派的模型,首先會(huì)通過(guò)遞歸從父加載器開(kāi)始找,
            // 直到父類(lèi)加載器是BootstrapClassLoader為止
            if (parent != null) {c = parent.loadClass(name, false);
            } else {c = findBootstrapClassOrNull(name);
            }
        } catch (ClassNotFoundException e) {}
        if (c == null) {// 如果還找不到,嘗試通過(guò)findClass方法去尋找
            // findClass是留給開(kāi)發(fā)者自己實(shí)現(xiàn)的,也就是說(shuō)
            // 自定義類(lèi)加載器時(shí),重寫(xiě)此方法即可
           c = findClass(name);
        }
    }
    if (resolve) {resolveClass(c);
    }
    return c;
    }
}
1.2 雙親委派模型缺陷

在雙親委派模型中,子類(lèi)加載器可以使用父類(lèi)加載器已經(jīng)加載的類(lèi),而父類(lèi)加載器無(wú)法使用子類(lèi)加載器已經(jīng)加載的。這就導(dǎo)致了雙親委派模型并不能解決所有的類(lèi)加載器問(wèn)題。

**案例:**Java 提供了很多服務(wù)提供者接口(Service Provider Interface,SPI),允許第三方為這些接口提供實(shí)現(xiàn)。常見(jiàn)的 SPI 有 JDBC、JNDI、JAXP 等,這些SPI的接口由核心類(lèi)庫(kù)提供,卻由第三方實(shí)現(xiàn),這樣就存在一個(gè)問(wèn)題:SPI 的接口是 Java 核心庫(kù)的一部分,是由BootstrapClassLoader加載的;SPI實(shí)現(xiàn)的Java類(lèi)一般是由AppClassLoader來(lái)加載的。BootstrapClassLoader是無(wú)法找到 SPI 的實(shí)現(xiàn)類(lèi)的,因?yàn)樗患虞dJava的核心庫(kù)。它也不能代理給AppClassLoader,因?yàn)樗亲铐攲拥念?lèi)加載器。也就是說(shuō),雙親委派模型并不能解決這個(gè)問(wèn)題。

1.3 使用線程上下文類(lèi)加載器(ContextClassLoader)加載

如果不做任何的設(shè)置,Java應(yīng)用的線程的上下文類(lèi)加載器默認(rèn)就是AppClassLoader。在核心類(lèi)庫(kù)使用SPI接口時(shí),傳遞的類(lèi)加載器使用線程上下文類(lèi)加載器,就可以成功的加載到SPI實(shí)現(xiàn)的類(lèi)。線程上下文類(lèi)加載器在很多SPI的實(shí)現(xiàn)中都會(huì)用到。

通常我們可以通過(guò)Thread.currentThread().getClassLoader()和Thread.currentThread().getContextClassLoader()獲取線程上下文類(lèi)加載器。

1.4 使用類(lèi)加載器加載資源文件,比如jar包

類(lèi)加載器除了加載class外,還有一個(gè)非常重要功能,就是加載資源,它可以從jar包中讀取任何資源文件,比如,ClassLoader.getResources(String name)方法就是用于讀取jar包中的資源文件。

//獲取資源的方法
public EnumerationgetResources(String name) throws IOException {Enumeration[] tmp = (Enumeration[]) new Enumeration[2];
    if (parent != null) {tmp[0] = parent.getResources(name);
    } else {tmp[0] = getBootstrapResources(name);
    }
    tmp[1] = findResources(name);
    return new CompoundEnumeration<>(tmp);
}

它的邏輯其實(shí)跟類(lèi)加載的邏輯是一樣的,首先判斷父類(lèi)加載器是否為空,不為空則委托父類(lèi)加載器執(zhí)行資源查找任務(wù),直到BootstrapClassLoader,最后才輪到自己查找。而不同的類(lèi)加載器負(fù)責(zé)掃描不同路徑下的jar包,就如同加載class一樣,最后會(huì)掃描所有的jar包,找到符合條件的資源文件。

// 使用線程上下文類(lèi)加載器加載資源
public static void main(String[] args) throws Exception{// Array.class的完整路徑
    String name = "java/sql/Array.class";
    Enumerationurls = Thread.currentThread().getContextClassLoader().getResources(name);
    while (urls.hasMoreElements()) {URL url = urls.nextElement();
        System.out.println(url.toString());
    }
}
二、Spring中SPI機(jī)制實(shí)現(xiàn) 2.1 SPI機(jī)制 2.1.1 SPI思想

SPI的全名為Service Provider Interface.這個(gè)是針對(duì)廠商或者插件的。

SPI的思想:系統(tǒng)里抽象的各個(gè)模塊,往往有很多不同的實(shí)現(xiàn)方案,比如日志模塊的方案,xml解析模塊、jdbc模塊的方案等。面向的對(duì)象的設(shè)計(jì)里,我們一般推薦模塊之間基于接口編程,模塊之間不對(duì)實(shí)現(xiàn)類(lèi)進(jìn)行硬編碼。一旦代碼里涉及具體的實(shí)現(xiàn)類(lèi),就違反了可拔插的原則,如果需要替換一種實(shí)現(xiàn),就需要修改代碼。為了實(shí)現(xiàn)在模塊裝配的時(shí)候能不在程序里動(dòng)態(tài)指明,這就需要一種服務(wù)發(fā)現(xiàn)機(jī)制。

java spi就是提供這樣的一個(gè)機(jī)制:為某個(gè)接口尋找服務(wù)實(shí)現(xiàn)的機(jī)制。

2.1.2 SPI約定

當(dāng)服務(wù)的提供者,提供了服務(wù)接口的一種實(shí)現(xiàn)之后,在jar包的META-INF/services/目錄里同時(shí)創(chuàng)建一個(gè)以服務(wù)接口命名的文件。該文件里就是實(shí)現(xiàn)該服務(wù)接口的具體實(shí)現(xiàn)類(lèi)。而當(dāng)外部程序裝配這個(gè)模塊的時(shí)候,就能通過(guò)該jar包META-INF/services/里的配置文件找到具體的實(shí)現(xiàn)類(lèi)名,并裝載實(shí)例化,完成模塊的注入。通過(guò)這個(gè)約定,就不需要把服務(wù)放在代碼中了,通過(guò)模塊被裝配的時(shí)候就可以發(fā)現(xiàn)服務(wù)類(lèi)了。

2.2 SPI使用案例

common-logging apache最早提供的日志的門(mén)面接口。只有接口,沒(méi)有實(shí)現(xiàn)。具體方案由各提供商實(shí)現(xiàn), 發(fā)現(xiàn)日志提供商是通過(guò)掃描 META-INF/services/org.apache.commons.logging.LogFactory配置文件,通過(guò)讀取該文件的內(nèi)容找到日志提工商實(shí)現(xiàn)類(lèi)。只要我們的日志實(shí)現(xiàn)里包含了這個(gè)文件,并在文件里制定 LogFactory工廠接口的實(shí)現(xiàn)類(lèi)即可。

2.3 Springboot中的類(lèi)SPI擴(kuò)展機(jī)制

在springboot的自動(dòng)裝配過(guò)程中,最終會(huì)加載META-INF/spring.factories文件,而加載的過(guò)程是由SpringFactoriesLoader加載的。從CLASSPATH下的每個(gè)Jar包中搜尋所有META-INF/spring.factories配置文件,然后將解析properties文件,找到指定名稱(chēng)的配置后返回。需要注意的是,其實(shí)這里不僅僅是會(huì)去ClassPath路徑下查找,會(huì)掃描所有路徑下的Jar包,只不過(guò)這個(gè)文件只會(huì)在Classpath下的jar包中。

public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
// spring.factories文件的格式為:key=value1,value2,value3
// 從所有的jar包中找到META-INF/spring.factories文件
// 然后從文件中解析出key=factoryClass類(lèi)名稱(chēng)的所有value值
public static ListloadFactoryNames(ClassfactoryClass, ClassLoader classLoader) {String factoryClassName = factoryClass.getName();
    // 取得資源文件的URL
    Enumerationurls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
    Listresult = new ArrayList();
    // 遍歷所有的URL
    while (urls.hasMoreElements()) {URL url = urls.nextElement();
        // 根據(jù)資源文件URL解析properties文件,得到對(duì)應(yīng)的一組@Configuration類(lèi)
        Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
        String factoryClassNames = properties.getProperty(factoryClassName);
        // 組裝數(shù)據(jù),并返回
        result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
    }
    return result;
}
三、源碼分析

先找到一個(gè)入口類(lèi)getSpringFactoriesInstances

3.1 getSpringFactoriesInstances

根據(jù)類(lèi)型獲取META-INF/spring.factories文件中對(duì)應(yīng)的實(shí)現(xiàn)類(lèi)

privateCollectiongetSpringFactoriesInstances(Classtype) {return getSpringFactoriesInstances(type, new Class[]{});
}

privateCollectiongetSpringFactoriesInstances(Classtype, Class[] parameterTypes, Object... args) {ClassLoader classLoader = getClassLoader();
    // Use names and ensure unique to protect against duplicates
    //從META-INF/spring.factories中加載對(duì)應(yīng)類(lèi)型的類(lèi)的自動(dòng)配置類(lèi)
    Setnames = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
    // 加載上來(lái)后反射實(shí)例化
    Listinstances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
    // 對(duì)實(shí)例列表進(jìn)行排序
    AnnotationAwareOrderComparator.sort(instances);
    return instances;
}
3.2 SpringFactoriesLoader

我們看看它的源碼(精簡(jiǎn)):

public abstract class SpringFactoriesLoader {private static final Log logger = LogFactory.getLog(SpringFactoriesLoader.class);

    public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";


    public staticListloadFactories(ClassfactoryClass, ClassLoader classLoader) {}

    public static ListloadFactoryNames(ClassfactoryClass, ClassLoader classLoader) {}
}

這個(gè)類(lèi)我們有利于我們繼續(xù)往下找線索的代碼是這一行:

public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

有了這一行代碼,我們大致就可以猜出來(lái)這個(gè)SpringFactoriesLoader類(lèi)大概是干嘛的了吧?它的兩個(gè)核心方法一個(gè)是用來(lái)尋找spring.factories文件中的Factory名稱(chēng)的,一個(gè)是用來(lái)尋找類(lèi)的。

3.3 loadFactoryNames

在該方法里,首先拿到ClassLoader,然后加載FactoryNames,加載類(lèi)型(type)為ApplicationContextInitializer,類(lèi)加載器(classLoader)為剛剛拿到的類(lèi)加載器,返回值放入一個(gè)Set中,為的是確保沒(méi)有重復(fù)的FactoryName,這是因?yàn)樵谥蠹虞d的兩個(gè)spring.factories配置文件中有兩個(gè)重復(fù)的FactoryName。

public static ListloadFactoryNames(ClassfactoryType, @Nullable ClassLoader classLoader) {String factoryTypeName = factoryType.getName();
    return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}

這一步是為了使用給定的ClassLoader去給定的FACTORIES_RESOURCE_LOCATION中加載全部的工廠類(lèi)

可以看到,加載的配置文件在META-INF下,名稱(chēng)為spring.factories,該配置文件一共有兩個(gè),且配置文件中,每個(gè)段落第一行為Key,后邊為value,讀取時(shí)會(huì)通過(guò)key將所有的value拿出來(lái)

在配置文件中我們發(fā)現(xiàn),key和value都是包名加類(lèi)名的字符串,因此Springboot在讀取文件后,是通過(guò)反射生成的類(lèi)

3.3.1 spring-boot-2.2.2.RELEASE.jar

file

該配置文件內(nèi)容如下:

# PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader

# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

# Error Reporters
org.springframework.boot.SpringBootExceptionReporter=\
org.springframework.boot.diagnostics.FailureAnalyzers

# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener

# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\
org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor,\
org.springframework.boot.reactor.DebugAgentEnvironmentPostProcessor

# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanDefinitionOverrideFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindValidationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoSuchMethodFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer

# FailureAnalysisReporters
org.springframework.boot.diagnostics.FailureAnalysisReporter=\
org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter
3.3.2 spring-boot-autoconfigure-2.2.2.RELEASE.jar

file

該配置文件內(nèi)容如下:

# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer

# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener

# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.rest.RestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration

# Failure analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\
org.springframework.boot.autoconfigure.flyway.FlywayMigrationScriptMissingFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer,\
org.springframework.boot.autoconfigure.session.NonUniqueSessionRepositoryFailureAnalyzer

# Template availability providers
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider
3.4 loadSpringFactories
private static Map>loadSpringFactories(@Nullable ClassLoader classLoader) {//到緩存中讀取
    MultiValueMapresult = cache.get(classLoader);
    //如果存在則直接返回
    if (result != null) {return result;
    }

    try {//獲取所以jar包META-INF/spring.factories對(duì)應(yīng)的URL
        Enumerationurls = (classLoader != null ?
                                 classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
                                 ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
        result = new LinkedMultiValueMap<>();
        //遍歷數(shù)據(jù)
        while (urls.hasMoreElements()) {URL url = urls.nextElement();
            //獲取到資源數(shù)據(jù)
            UrlResource resource = new UrlResource(url);
            //加載配置文件
            Properties properties = PropertiesLoaderUtils.loadProperties(resource);
            //遍歷解析配置文件
            for (Map.Entryentry : properties.entrySet()) {String factoryTypeName = ((String) entry.getKey()).trim();
                for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {//將spring.factories配置文件數(shù)據(jù)放進(jìn)結(jié)果集
                    result.add(factoryTypeName, factoryImplementationName.trim());
                }
            }
        }
        //加入緩存
        cache.put(classLoader, result);
        //返回結(jié)果
        return result;
    }
    catch (IOException ex) {throw new IllegalArgumentException("Unable to load factories from location [" +
                                           FACTORIES_RESOURCE_LOCATION + "]", ex);
    }
}

讀取完spring.factories后,把讀取到的內(nèi)容(13個(gè)key)存儲(chǔ)到枚舉類(lèi)中,然后遍歷枚舉類(lèi),將里邊內(nèi)容都add到一個(gè)map(result)里邊去,最后把classloader以及遍歷的結(jié)果都放入cache中,提高加載資源的效率。

3.5 createSpringFactoriesInstances

目前已經(jīng)取出所有的配置,但還沒(méi)有進(jìn)行初始化,該方法是實(shí)例化對(duì)象的

privateListcreateSpringFactoriesInstances(Classtype, Class[] parameterTypes,
                                                   ClassLoader classLoader, Object[] args, Setnames) {Listinstances = new ArrayList<>(names.size());
    for (String name : names) {try {ClassinstanceClass = ClassUtils.forName(name, classLoader);
            Assert.isAssignable(type, instanceClass);
            //獲取構(gòu)造方法
            Constructorconstructor = instanceClass.getDeclaredConstructor(parameterTypes);
            //實(shí)例化對(duì)象
            T instance = (T) BeanUtils.instantiateClass(constructor, args);
            //加入instances實(shí)例列表
            instances.add(instance);
        } catch (Throwable ex) {throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
        }
    }
    return instances;
}

本文由傳智教育博學(xué)谷教研團(tuán)隊(duì)發(fā)布。

如果本文對(duì)您有幫助,歡迎關(guān)注點(diǎn)贊;如果您有任何建議也可留言評(píng)論私信,您的支持是我堅(jiān)持創(chuàng)作的動(dòng)力。

轉(zhuǎn)載請(qǐng)注明出處!

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

新聞標(biāo)題:【源碼透視】SpringBoot的SPI機(jī)制-創(chuàng)新互聯(lián)
網(wǎng)頁(yè)地址:http://jinyejixie.com/article44/djeohe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信公眾號(hào)、企業(yè)建站靜態(tài)網(wǎng)站、云服務(wù)器關(guān)鍵詞優(yōu)化、網(wǎng)站內(nèi)鏈

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)
正镶白旗| 桦南县| 屏边| 洪洞县| 黄浦区| 洪江市| 会理县| 湖州市| 三门峡市| 县级市| 鹤壁市| 厦门市| 涟水县| 陈巴尔虎旗| 婺源县| 涟水县| 湟源县| 克东县| 宁明县| 鸡西市| 琼海市| 曲松县| 平江县| 察隅县| 新巴尔虎左旗| 抚州市| 清远市| 玛曲县| 阿鲁科尔沁旗| 灵寿县| 遂川县| 临澧县| 洛宁县| 荥阳市| 嵊泗县| 平果县| 通许县| 滁州市| 东辽县| 玉环县| 井陉县|