0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀(guān)看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Java、Spring、Dubbo三者SPI機(jī)制的原理和區(qū)別

jf_ro2CN3Fa ? 來(lái)源:三友的java日記 ? 2023-06-05 15:21 ? 次閱讀

今天來(lái)跟大家聊一聊Java、Spring、Dubbo三者SPI機(jī)制的原理和區(qū)別。

其實(shí)我之前寫(xiě)過(guò)一篇類(lèi)似的文章,但是這篇文章主要是剖析dubbo的SPI機(jī)制的源碼,中間只是簡(jiǎn)單地介紹了一下Java、Spring的SPI機(jī)制,并沒(méi)有進(jìn)行深入,所以本篇就來(lái)深入聊一聊這三者的原理和區(qū)別。

什么是SPI

SPI全稱(chēng)為Service Provider Interface,是一種動(dòng)態(tài)替換發(fā)現(xiàn)的機(jī)制,一種解耦非常優(yōu)秀的思想,SPI可以很靈活的讓接口和實(shí)現(xiàn)分離,讓api提供者只提供接口,第三方來(lái)實(shí)現(xiàn),然后可以使用配置文件的方式來(lái)實(shí)現(xiàn)替換或者擴(kuò)展,在框架中比較常見(jiàn),提高框架的可擴(kuò)展性。

簡(jiǎn)單來(lái)說(shuō)SPI是一種非常優(yōu)秀的設(shè)計(jì)思想,它的核心就是解耦、方便擴(kuò)展。

基于 Spring Boot + MyBatis Plus + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶(hù)小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶(hù)、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

項(xiàng)目地址:https://github.com/YunaiV/ruoyi-vue-pro

視頻教程:https://doc.iocoder.cn/video/

Java SPI機(jī)制--ServiceLoader

ServiceLoader是Java提供的一種簡(jiǎn)單的SPI機(jī)制的實(shí)現(xiàn),Java的SPI實(shí)現(xiàn)約定了以下兩件事:

文件必須放在META-INF/services/目錄底下

文件名必須為接口的全限定名,內(nèi)容為接口實(shí)現(xiàn)的全限定名

這樣就能夠通過(guò)ServiceLoader加載到文件中接口的實(shí)現(xiàn)。

來(lái)個(gè)demo

第一步,需要一個(gè)接口以及他的實(shí)現(xiàn)類(lèi)

publicinterfaceLoadBalance{
}

publicclassRandomLoadBalanceimplementsLoadBalance{
}

第二步,在META-INF/services/目錄創(chuàng)建一個(gè)文件名LoadBalance全限定名的文件,文件內(nèi)容為RandomLoadBalance的全限定名

36482d32-02a3-11ee-90ce-dac502259ad0.png36621418-02a3-11ee-90ce-dac502259ad0.png

測(cè)試類(lèi):

publicclassServiceLoaderDemo{

publicstaticvoidmain(String[]args){
ServiceLoaderloadBalanceServiceLoader=ServiceLoader.load(LoadBalance.class);
Iteratoriterator=loadBalanceServiceLoader.iterator();
while(iterator.hasNext()){
LoadBalanceloadBalance=iterator.next();
System.out.println("獲取到負(fù)載均衡策略:"+loadBalance);
}
}

}

測(cè)試結(jié)果:

36814fcc-02a3-11ee-90ce-dac502259ad0.png

此時(shí)就成功獲取到了實(shí)現(xiàn)。

在實(shí)際的框架設(shè)計(jì)中,上面這段測(cè)試代碼其實(shí)是框架作者寫(xiě)到框架內(nèi)部的,而對(duì)于框架的使用者來(lái)說(shuō),要想自定義LoadBalance實(shí)現(xiàn),嵌入到框架,僅僅只需要寫(xiě)接口的實(shí)現(xiàn)和spi文件即可。

實(shí)現(xiàn)原理

如下是ServiceLoader中一段核心代碼

36b0081c-02a3-11ee-90ce-dac502259ad0.png

首先獲取一個(gè)fullName,其實(shí)就是META-INF/services/接口的全限定名

36f39ff0-02a3-11ee-90ce-dac502259ad0.png

然后通過(guò)ClassLoader獲取到資源,其實(shí)就是接口的全限定名文件對(duì)應(yīng)的資源,然后交給parse方法解析資源

3725e2d0-02a3-11ee-90ce-dac502259ad0.png

parse方法其實(shí)就是通過(guò)IO流讀取文件的內(nèi)容,這樣就可以獲取到接口的實(shí)現(xiàn)的全限定名

再后面其實(shí)就是通過(guò)反射實(shí)例化對(duì)象,這里就不展示了。

所以其實(shí)不難發(fā)現(xiàn)ServiceLoader實(shí)現(xiàn)原理比較簡(jiǎn)單,總結(jié)起來(lái)就是通過(guò)IO流讀取META-INF/services/接口的全限定名文件的內(nèi)容,然后反射實(shí)例化對(duì)象。

優(yōu)缺點(diǎn)

由于Java的SPI機(jī)制實(shí)現(xiàn)的比較簡(jiǎn)單,所以他也有一些缺點(diǎn)。

第一點(diǎn)就是浪費(fèi)資源,雖然例子中只有一個(gè)實(shí)現(xiàn)類(lèi),但是實(shí)際情況下可能會(huì)有很多實(shí)現(xiàn)類(lèi),而Java的SPI會(huì)一股腦全進(jìn)行實(shí)例化,但是這些實(shí)現(xiàn)了不一定都用得著,所以就會(huì)白白浪費(fèi)資源。

第二點(diǎn)就是無(wú)法對(duì)區(qū)分具體的實(shí)現(xiàn),也就是這么多實(shí)現(xiàn)類(lèi),到底該用哪個(gè)實(shí)現(xiàn)呢?如果要判斷具體使用哪個(gè),只能依靠接口本身的設(shè)計(jì),比如接口可以設(shè)計(jì)為一個(gè)策略接口,又或者接口可以設(shè)計(jì)帶有優(yōu)先級(jí)的,但是不論怎樣設(shè)計(jì),框架作者都得寫(xiě)代碼進(jìn)行判斷。

所以總得來(lái)說(shuō)就是ServiceLoader無(wú)法做到按需加載或者按需獲取某個(gè)具體的實(shí)現(xiàn)。

使用場(chǎng)景

雖然說(shuō)ServiceLoader可能有些缺點(diǎn),但是還是有使用場(chǎng)景的,比如說(shuō):

不需要選擇具體的實(shí)現(xiàn),每個(gè)被加載的實(shí)現(xiàn)都需要被用到

雖然需要選擇具體的實(shí)現(xiàn),但是可以通過(guò)對(duì)接口的設(shè)計(jì)來(lái)解決

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶(hù)小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶(hù)、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

項(xiàng)目地址:https://github.com/YunaiV/yudao-cloud

視頻教程:https://doc.iocoder.cn/video/

Spring SPI機(jī)制--SpringFactoriesLoader

Spring我們都不陌生,他也提供了一種SPI的實(shí)現(xiàn)SpringFactoriesLoader。

Spring的SPI機(jī)制的約定如下:

配置文件必須在META-INF/目錄下,文件名必須為spring.factories

文件內(nèi)容為鍵值對(duì),一個(gè)鍵可以有多個(gè)值,只需要用逗號(hào)分割就行,同時(shí)鍵值都需要是類(lèi)的全限定名,鍵和值可以沒(méi)有任何類(lèi)與類(lèi)之間的關(guān)系,當(dāng)然也可以有實(shí)現(xiàn)的關(guān)系。

所以也可以看出,Spring的SPI機(jī)制跟Java的不論是文件名還是內(nèi)容約定都不一樣。

來(lái)個(gè)demo

在META-INF/目錄下創(chuàng)建spring.factories文件,LoadBalance為鍵,RandomLoadBalance為值

375b7526-02a3-11ee-90ce-dac502259ad0.png3778872e-02a3-11ee-90ce-dac502259ad0.png

測(cè)試:

publicclassSpringFactoriesLoaderDemo{

publicstaticvoidmain(String[]args){
ListloadBalances=SpringFactoriesLoader.loadFactories(LoadBalance.class,MyEnableAutoConfiguration.class.getClassLoader());
for(LoadBalanceloadBalance:loadBalances){
System.out.println("獲取到LoadBalance對(duì)象:"+loadBalance);
}
}

}

運(yùn)行結(jié)果:

379c26b6-02a3-11ee-90ce-dac502259ad0.png

成功獲取到了實(shí)現(xiàn)對(duì)象。

核心原理

如下是SpringFactoriesLoader中一段核心代碼

37c72f8c-02a3-11ee-90ce-dac502259ad0.png

其實(shí)從這可以看出,跟Java實(shí)現(xiàn)的差不多,只不過(guò)讀的是META-INF/目錄下spring.factories文件內(nèi)容,然后解析出來(lái)鍵值對(duì)。

使用場(chǎng)景

Spring的SPI機(jī)制在內(nèi)部使用的非常多,尤其在SpringBoot中大量使用,SpringBoot啟動(dòng)過(guò)程中很多擴(kuò)展點(diǎn)都是通過(guò)SPI機(jī)制來(lái)實(shí)現(xiàn)的,這里我舉兩個(gè)例子

1、自動(dòng)裝配

在SpringBoot3.0之前的版本,自動(dòng)裝配是通過(guò)SpringFactoriesLoader來(lái)加載的。

37f9d3f6-02a3-11ee-90ce-dac502259ad0.png

但是SpringBoot3.0之后不再使用SpringFactoriesLoader,而是Spring重新從META-INF/spring/目錄下的org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中讀取了。

38366dfc-02a3-11ee-90ce-dac502259ad0.png

至于如何讀取的,其實(shí)猜也能猜到就跟上面SPI機(jī)制讀取的方式大概差不多,就是文件路徑和名稱(chēng)不一樣。

2、PropertySourceLoader的加載

PropertySourceLoader是用來(lái)解析application配置文件的,它是一個(gè)接口

38716c18-02a3-11ee-90ce-dac502259ad0.png

SpringBoot默認(rèn)提供了 PropertiesPropertySourceLoader 和 YamlPropertySourceLoader兩個(gè)實(shí)現(xiàn),就是對(duì)應(yīng)properties和yaml文件格式的解析。

SpringBoot在加載PropertySourceLoader時(shí)就用了SPI機(jī)制

38a7afc6-02a3-11ee-90ce-dac502259ad0.png

與Java SPI機(jī)制對(duì)比

首先Spring的SPI機(jī)制對(duì)Java的SPI機(jī)制對(duì)進(jìn)行了一些簡(jiǎn)化,Java的SPI每個(gè)接口都需要對(duì)應(yīng)的文件,而Spring的SPI機(jī)制只需要一個(gè)spring.factories文件。

其次是內(nèi)容,Java的SPI機(jī)制文件內(nèi)容必須為接口的實(shí)現(xiàn)類(lèi),而Spring的SPI并不要求鍵值對(duì)必須有什么關(guān)系,更加靈活。

第三點(diǎn)就是Spring的SPI機(jī)制提供了獲取類(lèi)限定名的方法loadFactoryNames,而Java的SPI機(jī)制是沒(méi)有的。通過(guò)這個(gè)方法獲取到類(lèi)限定名之后就可以將這些類(lèi)注入到Spring容器中,用Spring容器加載這些Bean,而不僅僅是通過(guò)反射。

但是Spring的SPI也同樣沒(méi)有實(shí)現(xiàn)獲取指定某個(gè)指定實(shí)現(xiàn)類(lèi)的功能,所以要想能夠找到具體的某個(gè)實(shí)現(xiàn)類(lèi),還得依靠具體接口的設(shè)計(jì)。

所以不知道你有沒(méi)有發(fā)現(xiàn),PropertySourceLoader它其實(shí)就是一個(gè)策略接口,注釋也有說(shuō),所以當(dāng)你的配置文件是properties格式的時(shí)候,他可以找到解析properties格式的PropertiesPropertySourceLoader對(duì)象來(lái)解析配置文件。

Dubbo SPI機(jī)制--ExtensionLoader

ExtensionLoader是dubbo的SPI機(jī)制的實(shí)現(xiàn)類(lèi)。每一個(gè)接口都會(huì)有一個(gè)自己的ExtensionLoader實(shí)例對(duì)象,這點(diǎn)跟Java的SPI機(jī)制是一樣的。

同樣地,Dubbo的SPI機(jī)制也做了以下幾點(diǎn)約定:

接口必須要加@SPI注解

配置文件可以放在META-INF/services/、META-INF/dubbo/internal/ 、META-INF/dubbo/ 、META-INF/dubbo/external/這四個(gè)目錄底下,文件名也是接口的全限定名

內(nèi)容為鍵值對(duì),鍵為短名稱(chēng)(可以理解為spring中Bean的名稱(chēng)),值為實(shí)現(xiàn)類(lèi)的全限定名

先來(lái)個(gè)demo

首先在LoadBalance接口上@SPI注解

@SPI
publicinterfaceLoadBalance{

}

然后,修改一下Java的SPI機(jī)制測(cè)試時(shí)配置文件內(nèi)容,改為鍵值對(duì),因?yàn)镈ubbo的SPI機(jī)制也可以從META-INF/services/目錄下讀取文件,所以這里就沒(méi)重寫(xiě)文件

random=com.sanyou.spi.demo.RandomLoadBalance

測(cè)試類(lèi):

publicclassExtensionLoaderDemo{

publicstaticvoidmain(String[]args){
ExtensionLoaderextensionLoader=ExtensionLoader.getExtensionLoader(LoadBalance.class);
LoadBalanceloadBalance=extensionLoader.getExtension("random");
System.out.println("獲取到random鍵對(duì)應(yīng)的實(shí)現(xiàn)類(lèi)對(duì)象:"+loadBalance);
}

}

通過(guò)ExtensionLoader的getExtension方法,傳入短名稱(chēng),這樣就可以精確地找到短名稱(chēng)對(duì)的實(shí)現(xiàn)類(lèi)。

所以從這可以看出Dubbo的SPI機(jī)制解決了前面提到的無(wú)法獲取指定實(shí)現(xiàn)類(lèi)的問(wèn)題。

測(cè)試結(jié)果:

38d96566-02a3-11ee-90ce-dac502259ad0.png

dubbo的SPI機(jī)制除了解決了無(wú)法獲取指定實(shí)現(xiàn)類(lèi)的問(wèn)題,還提供了很多額外的功能,這些功能在dubbo內(nèi)部用的非常多,接下來(lái)就來(lái)詳細(xì)講講。

dubbo核心機(jī)制

1、自適應(yīng)機(jī)制

自適應(yīng),自適應(yīng)擴(kuò)展類(lèi)的含義是說(shuō),基于參數(shù),在運(yùn)行時(shí)動(dòng)態(tài)選擇到具體的目標(biāo)類(lèi),然后執(zhí)行。

每個(gè)接口有且只能有一個(gè)自適應(yīng)類(lèi),通過(guò)ExtensionLoader的getAdaptiveExtension方法就可以獲取到這個(gè)類(lèi)的對(duì)象,這個(gè)對(duì)象可以根據(jù)運(yùn)行時(shí)具體的參數(shù)找到目標(biāo)實(shí)現(xiàn)類(lèi)對(duì)象,然后調(diào)用目標(biāo)對(duì)象的方法。

舉個(gè)例子,假設(shè)上面的LoadBalance有個(gè)自適應(yīng)對(duì)象,那么獲取到這個(gè)自適應(yīng)對(duì)象之后,如果在運(yùn)行期間傳入了random這個(gè)key,那么這個(gè)自適應(yīng)對(duì)象就會(huì)找到random這個(gè)key對(duì)應(yīng)的實(shí)現(xiàn)類(lèi),調(diào)用那個(gè)實(shí)現(xiàn)類(lèi)的方法,如果動(dòng)態(tài)傳入了其它的key,就路由到其它的實(shí)現(xiàn)類(lèi)。

自適應(yīng)類(lèi)有兩種方式產(chǎn)生,第一種就是自己指定,在接口的實(shí)現(xiàn)類(lèi)上加@Adaptive注解,那么這個(gè)這個(gè)實(shí)現(xiàn)類(lèi)就是自適應(yīng)實(shí)現(xiàn)類(lèi)。

@Adaptive
publicclassRandomLoadBalanceimplementsLoadBalance{
}

除了自己代碼指定,還有一種就是dubbo會(huì)根據(jù)一些條件幫你動(dòng)態(tài)生成一個(gè)自適應(yīng)類(lèi),生成過(guò)程比較復(fù)雜,這里就不展開(kāi)了。

自適應(yīng)機(jī)制在Dubbo中用的非常多,而且很多都是自動(dòng)生成的,如果你不知道Dubbo的自適應(yīng)機(jī)制,你在讀源碼的時(shí)候可能都不知道為什么代碼可以走到那里。。

2、IOC和AOP

一提到IOC和AOP,立馬想到的都是Spring,但是IOC和AOP并不是Spring特有的概念,Dubbo也實(shí)現(xiàn)IOC和AOP的功能,但是是一個(gè)輕量級(jí)的。

2.1、依賴(lài)注入

Dubbo依賴(lài)注入是通過(guò)setter注入的方式,注入的對(duì)象默認(rèn)就是上面提到的自適應(yīng)的對(duì)象,在Spring環(huán)境下可以注入Spring Bean。

publicclassRoundRobinLoadBalanceimplementsLoadBalance{

privateLoadBalanceloadBalance;

publicvoidsetLoadBalance(LoadBalanceloadBalance){
this.loadBalance=loadBalance;
}

}

如上代碼,RoundRobinLoadBalance中有一個(gè)setLoadBalance方法,參數(shù)LoadBalance,在創(chuàng)建RoundRobinLoadBalance的時(shí)候,在非Spring環(huán)境底下,Dubbo就會(huì)找到LoadBalance自適應(yīng)對(duì)象然后通過(guò)反射注入。

這種方式在Dubbo中也很常見(jiàn),比如如下的一個(gè)場(chǎng)景

39029850-02a3-11ee-90ce-dac502259ad0.png

RegistryProtocol中會(huì)注入一個(gè)Protocol,其實(shí)這個(gè)注入的Protocol就是一個(gè)自適應(yīng)對(duì)象。

2.2、接口回調(diào)

Dubbo也提供了一些類(lèi)似于Spring的一些接口的回調(diào)功能,比如說(shuō),如果你的類(lèi)實(shí)現(xiàn)了Lifecycle接口,那么創(chuàng)建或者銷(xiāo)毀的時(shí)候就會(huì)回調(diào)以下幾個(gè)方法

39245b0c-02a3-11ee-90ce-dac502259ad0.png

在dubbo3.x的某個(gè)版本之后,dubbo提供了更多接口回調(diào),比如說(shuō)ExtensionPostProcessor、ExtensionAccessorAware,命名跟Spring的非常相似,作用也差不多。

2.3、自動(dòng)包裝

自動(dòng)包裝其實(shí)就是aop的功能實(shí)現(xiàn),對(duì)目標(biāo)對(duì)象進(jìn)行代理,并且這個(gè)aop功能在默認(rèn)情況下就是開(kāi)啟的。

在Dubbo中SPI接口的實(shí)現(xiàn)中,有一種特殊的類(lèi),被稱(chēng)為Wrapper類(lèi),這個(gè)類(lèi)的作用就是來(lái)實(shí)現(xiàn)AOP的。

判斷Wrapper類(lèi)的唯一標(biāo)準(zhǔn)就是這個(gè)類(lèi)中必須要有這么一個(gè)構(gòu)造參數(shù),這個(gè)構(gòu)造方法的參數(shù)只有一個(gè),并且參數(shù)類(lèi)型就是接口的類(lèi)型,如下代碼:

publicclassRoundRobinLoadBalanceimplementsLoadBalance{

privatefinalLoadBalanceloadBalance;

publicRoundRobinLoadBalance(LoadBalanceloadBalance){
this.loadBalance=loadBalance;
}

}

此時(shí)RoundRobinLoadBalance就是一個(gè)Wrapper類(lèi)。

當(dāng)通過(guò)random獲取RandomLoadBalance目標(biāo)對(duì)象時(shí),那么默認(rèn)情況下就會(huì)對(duì)RandomLoadBalance進(jìn)行包裝,真正獲取到的其實(shí)是RoundRobinLoadBalance對(duì)象,RoundRobinLoadBalance內(nèi)部引用的對(duì)象是RandomLoadBalance。

*測(cè)試一下 *

在配置文件中加入

roundrobin=com.sanyou.spi.demo.RoundRobinLoadBalance

測(cè)試結(jié)果

395360be-02a3-11ee-90ce-dac502259ad0.png

從結(jié)果可以看出,雖然指定了random,但是實(shí)際獲取到的是RoundRobinLoadBalance,而RoundRobinLoadBalance內(nèi)部引用了RandomLoadBalance。

如果有很多的包裝類(lèi),那么就會(huì)形成一個(gè)責(zé)任鏈條,一個(gè)套一個(gè)。

所以dubbo的aop跟spring的aop實(shí)現(xiàn)是不一樣的,spring的aop底層是基于動(dòng)態(tài)代理來(lái)的,而dubbo的aop其實(shí)算是靜態(tài)代理,dubbo會(huì)幫你自動(dòng)組裝這個(gè)代理,形成一條責(zé)任鏈。

到這其實(shí)我們已經(jīng)知道,dubbo的spi接口的實(shí)現(xiàn)類(lèi)已經(jīng)有兩種類(lèi)型了:

自適應(yīng)類(lèi)

Wrapper類(lèi)

除了這兩種類(lèi)型,其實(shí)還有一種,叫做默認(rèn)類(lèi),就是@SPI注解的值對(duì)應(yīng)的實(shí)現(xiàn)類(lèi),比如

@SPI("random")
publicinterfaceLoadBalance{

}

此時(shí)random這個(gè)key對(duì)應(yīng)的實(shí)現(xiàn)類(lèi)就是默認(rèn)實(shí)現(xiàn),通過(guò)getDefaultExtension這個(gè)方法就可以獲取到默認(rèn)實(shí)現(xiàn)對(duì)象。

3、自動(dòng)激活

所謂的自動(dòng)激活,就是根據(jù)你的入?yún)?,?dòng)態(tài)地選擇一批實(shí)現(xiàn)類(lèi)返回給你。

自動(dòng)激活的實(shí)現(xiàn)類(lèi)上需要加上Activate注解,這里就又學(xué)習(xí)了一種實(shí)現(xiàn)類(lèi)的分類(lèi)。

@Activate
publicinterfaceRandomLoadBalance{

}

此時(shí)RandomLoadBalance就屬于可以被自動(dòng)激活的類(lèi)。

獲取自動(dòng)激活類(lèi)的方法是getActivateExtension,所以根據(jù)這個(gè)方法的入?yún)?,可以?dòng)態(tài)選擇一批實(shí)現(xiàn)類(lèi)。

自動(dòng)激活這個(gè)機(jī)制在Dubbo一個(gè)核心的使用場(chǎng)景就是Filter過(guò)濾器鏈中。

Filter是dubbo中的一個(gè)擴(kuò)展點(diǎn),可以在請(qǐng)求發(fā)起前或者是響應(yīng)獲取之后就行攔截,作用有點(diǎn)像Spring MVC中的HandlerInterceptor。

39973640-02a3-11ee-90ce-dac502259ad0.pngFilter的一些實(shí)現(xiàn)類(lèi)

如上Filter有很多實(shí)現(xiàn),所以為了能夠區(qū)分Filter的實(shí)現(xiàn)是作用于provider的還是consumer端,所以就可以用自動(dòng)激活的機(jī)制來(lái)根據(jù)入?yún)?lái)動(dòng)態(tài)選擇一批Filter實(shí)現(xiàn)。

比如說(shuō)ConsumerContextFilter這個(gè)Filter就作用于Consumer端。

39c4e018-02a3-11ee-90ce-dac502259ad0.pngConsumerContextFilter

總結(jié)

通過(guò)以上分析可以看出,實(shí)現(xiàn)SPI機(jī)制的核心原理就是通過(guò)IO流讀取指定文件的內(nèi)容,然后解析,最后加入一些自己的特性。

最后總的來(lái)說(shuō),Java的SPI實(shí)現(xiàn)的比較簡(jiǎn)單,并沒(méi)有什么其它功能;Spring得益于自身的ioc和aop的功能,所以也沒(méi)有實(shí)現(xiàn)太復(fù)雜的SPI機(jī)制,僅僅是對(duì)Java做了一點(diǎn)簡(jiǎn)化和優(yōu)化;但是dubbo的SPI機(jī)制為了滿(mǎn)足自身框架的使用要求,實(shí)現(xiàn)的功能就比較多,不僅將ioc和aop的功能集成到SPI機(jī)制中,還提供注入自適應(yīng)和自動(dòng)激活等功能。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀(guān)點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • JAVA
    +關(guān)注

    關(guān)注

    19

    文章

    2952

    瀏覽量

    104482
  • SPI
    SPI
    +關(guān)注

    關(guān)注

    17

    文章

    1688

    瀏覽量

    91213
  • 源碼
    +關(guān)注

    關(guān)注

    8

    文章

    632

    瀏覽量

    29110
  • spring
    +關(guān)注

    關(guān)注

    0

    文章

    338

    瀏覽量

    14295
  • Dubbo
    +關(guān)注

    關(guān)注

    0

    文章

    19

    瀏覽量

    3165

原文標(biāo)題:聊聊SPI

文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    java spring教程

    java spring教程理解Spring 實(shí)現(xiàn)原理掌握Spring IOC,AOP掌握Spring的基礎(chǔ)配置和用法熟練使用SSH開(kāi)發(fā)項(xiàng)目
    發(fā)表于 09-11 11:09

    什么是java spring

    什么是java springSpring是一個(gè)開(kāi)源框架,它由Rod Johnson創(chuàng)建。它是為了解決企業(yè)應(yīng)用開(kāi)發(fā)的復(fù)雜性而創(chuàng)建的。Spring使用基本的JavaBean來(lái)完成以前只可能由EJB完成
    發(fā)表于 09-11 11:16

    聊聊Dubbo - Dubbo可擴(kuò)展機(jī)制實(shí)戰(zhàn)

    OSGI容器Dubbo作為一個(gè)框架,不希望強(qiáng)依賴(lài)其他的IoC容器,比如Spring,Guice。OSGI也是一個(gè)很重的實(shí)現(xiàn),不適合Dubbo。最終Dubbo的實(shí)現(xiàn)參考了
    發(fā)表于 06-04 17:33

    聊聊Dubbo - Dubbo可擴(kuò)展機(jī)制源碼解析

    的場(chǎng)景中,類(lèi)之間都是有依賴(lài)的。擴(kuò)展實(shí)例中也會(huì)引用一些依賴(lài),比如簡(jiǎn)單的Java類(lèi),另一個(gè)Dubbo的擴(kuò)展或一個(gè)Spring Bean等。依賴(lài)的情況很復(fù)雜,Dubbo的處理也相對(duì)復(fù)雜些。我
    發(fā)表于 06-05 18:43

    Dubbo開(kāi)源現(xiàn)狀與未來(lái)規(guī)劃

    考慮到有些同學(xué)可能對(duì) Dubbo 不太熟悉,我先簡(jiǎn)單介紹下 Dubbo 的工作原理和架構(gòu)。簡(jiǎn)單的說(shuō),Dubbo 是 基于 Java 的 RPC 框架。
    發(fā)表于 07-05 15:21

    Dubbo Cloud Native 之路的實(shí)踐與思考

    Jaeger,三者的靈感均來(lái)自于 Google 論文 Dapper。相對(duì)而言,Java 程序員可能更為熟悉 Zipkin,因?yàn)樗?Spring Cloud Sleuth 首選方案,提供客戶(hù)端
    發(fā)表于 07-05 16:05

    請(qǐng)問(wèn)xdata和bdata和普通變量三者有什么區(qū)別?

    如題,請(qǐng)問(wèn)xdata和bdata和普通變量三者區(qū)別?
    發(fā)表于 09-11 04:35

    UART SPI IIC的詳解及三者區(qū)別和聯(lián)系

    詳情參考文章01詳情參考文章02UART SPI IIC的詳解及三者區(qū)別和聯(lián)系A(chǔ)rduino主從機(jī)之間的i2c通信I2C總線(xiàn)定義:I2C(‘intel’ -Integrated Circuit
    發(fā)表于 12-13 07:27

    USART,串口和USB這三者區(qū)別

    參考文獻(xiàn):區(qū)分:串口,COM口,UART,USART,串口和USB這三者區(qū)別1.串口 COM UART JTAG(它們是一個(gè)類(lèi)別的,對(duì)應(yīng)的是硬件,區(qū)別是設(shè)備...
    發(fā)表于 12-16 06:51

    ADISimPE和ADISimRF,ADISimPLL三者有什么區(qū)別?

    為什么在A(yíng)DIsimPE中找不到ADL系列的仿真模型,比如ADL5535,。 而且請(qǐng)問(wèn)ADISimPE和ADISimRF,ADISimPLL三者有什么區(qū)別
    發(fā)表于 11-17 11:32

    Dubbo源代碼實(shí)現(xiàn)服務(wù)調(diào)用的動(dòng)態(tài)代理和負(fù)載均衡

    。現(xiàn)在,我們從源碼的角度來(lái)看看,Dubbo是如何做到這點(diǎn)的。我們知道,要成為Dubbo服務(wù)的消費(fèi),需要在Spring的xml文件中配置
    發(fā)表于 03-12 14:35 ?0次下載

    介紹PWM、 PPM、S-BUS這三者區(qū)別

    介紹PWM、PPM、S-BUS這三者區(qū)別
    的頭像 發(fā)表于 03-08 11:32 ?7713次閱讀

    JDK內(nèi)置的一種服務(wù)SPI機(jī)制

    SPI(Service Provider Interface)是JDK內(nèi)置的一種服務(wù)提供發(fā)現(xiàn)機(jī)制,可以用來(lái)啟用框架擴(kuò)展和替換組件,主要用于框架中開(kāi)發(fā),例如Dubbo、Spring
    的頭像 發(fā)表于 02-15 09:15 ?763次閱讀

    基于springSPI擴(kuò)展機(jī)制是如何實(shí)現(xiàn)的?

    基本上,你一說(shuō)是基于 springSPI 擴(kuò)展機(jī)制,再把spring.factories文件和EnableAutoConfiguration提一下,那么這個(gè)問(wèn)題就答的八九不離十了
    的頭像 發(fā)表于 03-07 09:17 ?988次閱讀

    dubbospring cloud區(qū)別

    DubboSpring Cloud是兩個(gè)非常流行的微服務(wù)框架,各有自己的特點(diǎn)和優(yōu)勢(shì)。在本文中,我們將詳細(xì)介紹DubboSpring Cloud的
    的頭像 發(fā)表于 12-04 14:47 ?1549次閱讀