溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Dubbo中SPI的相關(guān)介紹

發(fā)布時間:2021-06-28 14:56:05 來源:億速云 閱讀:113 作者:chen 欄目:大數(shù)據(jù)

本篇內(nèi)容主要講解“Dubbo中SPI的相關(guān)介紹”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“Dubbo中SPI的相關(guān)介紹”吧!

為什么要設(shè)計adaptive?注解在類上和注解在方法上的區(qū)別?
adaptive設(shè)計的目的是為了識別固定已知類和擴(kuò)展未知類。
1.注解在類上:代表人工實(shí)現(xiàn),實(shí)現(xiàn)一個裝飾類(設(shè)計模式中的裝飾模式),它主要作用于固定已知類,
  目前整個系統(tǒng)只有2個,AdaptiveCompiler、AdaptiveExtensionFactory。
  a.為什么AdaptiveCompiler這個類是固定已知的?因?yàn)檎麄€框架僅支持Javassist和JdkCompiler。
  b.為什么AdaptiveExtensionFactory這個類是固定已知的?因?yàn)檎麄€框架僅支持2個objFactory,一個是spi,另一個是spring
2.注解在方法上:代表自動生成和編譯一個動態(tài)的Adpative類,它主要是用于SPI,因?yàn)閟pi的類是不固定、未知的擴(kuò)展類,所以設(shè)計了動態(tài)$Adaptive類.
例如 Protocol的spi類有 injvm dubbo registry filter listener等等 很多擴(kuò)展未知類,
它設(shè)計了Protocol$Adaptive的類,通過ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(spi類);來提取對象


為什么dubbo要自己設(shè)計一套SPI?
這是原始JDK spi的代碼
    ServiceLoader<Command> serviceLoader=ServiceLoader.load(Command.class); 
  for(Command command:serviceLoader){  
      command.execute();  
  }  
dubbo在原來的基礎(chǔ)上設(shè)計了以下功能
1.原始JDK spi不支持緩存;dubbo設(shè)計了緩存對象:spi的key與value 緩存在 cachedInstances對象里面,它是一個ConcurrentMap
2.原始JDK spi不支持默認(rèn)值,dubbo設(shè)計默認(rèn)值:@SPI("dubbo") 代表默認(rèn)的spi對象,例如Protocol的@SPI("dubbo")就是 DubboProtocol,
  通過 ExtensionLoader.getExtensionLoader(Protocol.class).getDefaultExtension()那默認(rèn)對象
3.jdk要用for循環(huán)判斷對象,dubbo設(shè)計getExtension靈活方便,動態(tài)獲取spi對象,
  例如 ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(spi的key)來提取對象
4.原始JDK spi不支持 AOP功能,dubbo設(shè)計增加了AOP功能,在cachedWrapperClasses,在原始spi類,包裝了XxxxFilterWrapper XxxxListenerWrapper
5.原始JDK spi不支持 IOC功能,dubbo設(shè)計增加了IOC,通過構(gòu)造函數(shù)注入,代碼為:wrapperClass.getConstructor(type).newInstance(instance),

dubbo spi 的目的:獲取一個指定實(shí)現(xiàn)類的對象。
途徑:ExtensionLoader.getExtension(String name)
實(shí)現(xiàn)路徑:
getExtensionLoader(Class<T> type) 就是為該接口new 一個ExtensionLoader,然后緩存起來。
getAdaptiveExtension() 獲取一個擴(kuò)展類,如果@Adaptive注解在類上就是一個裝飾類;如果注解在方法上就是一個動態(tài)代理類,例如Protocol$Adaptive對象。
getExtension(String name) 獲取一個指定對象。


-----------------------ExtensionLoader.getExtensionLoader(Class<T> type)
ExtensionLoader.getExtensionLoader(Container.class)
  -->this.type = type;
  -->objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
     -->ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()
       -->this.type = type;
       -->objectFactory =null;
       
執(zhí)行以上代碼完成了2個屬性的初始化
1.每個一個ExtensionLoader都包含了2個值 type 和 objectFactory
  Class<?> type;//構(gòu)造器  初始化時要得到的接口名
  ExtensionFactory objectFactory//構(gòu)造器  初始化時 AdaptiveExtensionFactory[SpiExtensionFactory,SpringExtensionFactory]
2.new 一個ExtensionLoader 存儲在ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS

關(guān)于這個objectFactory的一些細(xì)節(jié):
1.objectFactory就是ExtensionFactory,它也是通過ExtensionLoader.getExtensionLoader(ExtensionFactory.class)來實(shí)現(xiàn)的,但是它的objectFactory=null
2.objectFactory作用,它就是為dubbo的IOC提供所有對象。
       

-----------------------getAdaptiveExtension()


-->getAdaptiveExtension()//為cachedAdaptiveInstance賦值
  -->createAdaptiveExtension()
    -->getAdaptiveExtensionClass()
      -->getExtensionClasses()//為cachedClasses 賦值
        -->loadExtensionClasses()
          -->loadFile
      -->createAdaptiveExtensionClass()//自動生成和編譯一個動態(tài)的adpative類,這個類是一個代理類
        -->ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension()
        -->compiler.compile(code, classLoader)
    -->injectExtension()//作用:進(jìn)入IOC的反轉(zhuǎn)控制模式,實(shí)現(xiàn)了動態(tài)入注
        
          
關(guān)于loadfile的一些細(xì)節(jié)
目的:通過把配置文件META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol的內(nèi)容,存儲在緩存變量里面。
cachedAdaptiveClass//如果這個class含有adative注解就賦值,例如ExtensionFactory,而例如Protocol在這個環(huán)節(jié)是沒有的。
cachedWrapperClasses//只有當(dāng)該class無adative注解,并且構(gòu)造函數(shù)包含目標(biāo)接口(type)類型,
                                                                 例如protocol里面的spi就只有ProtocolFilterWrapper和ProtocolListenerWrapper能命中
cachedActivates//剩下的類,包含Activate注解
cachedNames//剩下的類就存儲在這里。

-----------------------getExtension(String name)
getExtension(String name) //指定對象緩存在cachedInstances;get出來的對象wrapper對象,例如protocol就是ProtocolFilterWrapper和ProtocolListenerWrapper其中一個。
  -->createExtension(String name)
    -->getExtensionClasses()
    -->injectExtension(T instance)//dubbo的IOC反轉(zhuǎn)控制,就是從spi和spring里面提取對象賦值。
      -->objectFactory.getExtension(pt, property)
        -->SpiExtensionFactory.getExtension(type, name)
          -->ExtensionLoader.getExtensionLoader(type)
          -->loader.getAdaptiveExtension()
        -->SpringExtensionFactory.getExtension(type, name)
          -->context.getBean(name)
    -->injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance))//AOP的簡單設(shè)計
    

到此,相信大家對“Dubbo中SPI的相關(guān)介紹”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI