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

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

創(chuàng)新互聯(lián)專注于馬鞍山企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站設(shè)計(jì),成都做商城網(wǎng)站。馬鞍山網(wǎng)站建設(shè)公司,為馬鞍山等地區(qū)提供建站服務(wù)。全流程定制網(wǎng)站制作,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

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


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

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


-----------------------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個(gè)屬性的初始化
1.每個(gè)一個(gè)ExtensionLoader都包含了2個(gè)值 type 和 objectFactory
  Class<?> type;//構(gòu)造器  初始化時(shí)要得到的接口名
  ExtensionFactory objectFactory//構(gòu)造器  初始化時(shí) AdaptiveExtensionFactory[SpiExtensionFactory,SpringExtensionFactory]
2.new 一個(gè)ExtensionLoader 存儲(chǔ)在ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS

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

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


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

-----------------------getExtension(String name)
getExtension(String name) //指定對(duì)象緩存在cachedInstances;get出來(lái)的對(duì)象wrapper對(duì)象,例如protocol就是ProtocolFilterWrapper和ProtocolListenerWrapper其中一個(gè)。
  -->createExtension(String name)
    -->getExtensionClasses()
    -->injectExtension(T instance)//dubbo的IOC反轉(zhuǎn)控制,就是從spi和spring里面提取對(duì)象賦值。
      -->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的簡(jiǎn)單設(shè)計(jì)
    

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

分享名稱:Dubbo中SPI的相關(guān)介紹
鏈接地址:http://bm7419.com/article8/gijoip.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供動(dòng)態(tài)網(wǎng)站自適應(yīng)網(wǎng)站、域名注冊(cè)、網(wǎng)站收錄、微信公眾號(hào)、用戶體驗(yàn)

廣告

聲明:本網(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)

成都網(wǎng)站建設(shè)