dubbo源碼閱讀之spi

為什么要設(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的類,通過ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(spi類);來提取對(duì)象

為什么dubbo要自己設(shè)計(jì)一套SPI啥刻?

這是原始JDK spi的代碼

ServiceLoader<Command> serviceLoader=ServiceLoader.load(Command.class);?

? for(Command command:serviceLoader){??

? ? ? command.execute();??

? }??

dubbo在原來的基礎(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,

? 通過 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)來提取對(duì)象

4.原始JDK spi不支持 AOP功能申窘,dubbo設(shè)計(jì)增加了AOP功能,在cachedWrapperClasses弯蚜,在原始spi類孔轴,包裝了XxxxFilterWrapper XxxxListenerWrapper

5.原始JDK spi不支持 IOC功能剃法,dubbo設(shè)計(jì)增加了IOC,通過構(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路鹰,然后緩存起來贷洲。

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,它也是通過ExtensionLoader.getExtensionLoader(ExtensionFactory.class)來實(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é)

目的:通過把配置文件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無adative注解屯掖,并且構(gòu)造函數(shù)包含目標(biāo)接口(type)類型,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?例如protocol里面的spi就只有ProtocolFilterWrapper和ProtocolListenerWrapper能命中

cachedActivates//剩下的類襟衰,包含Activate注解

cachedNames//剩下的類就存儲(chǔ)在這里懂扼。

-----------------------getExtension(String name)

getExtension(String name) //指定對(duì)象緩存在cachedInstances;get出來的對(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的簡單設(shè)計(jì)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末陷嘴,一起剝皮案震驚了整個(gè)濱河市映砖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌灾挨,老刑警劉巖邑退,帶你破解...
    沈念sama閱讀 223,207評(píng)論 6 521
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異劳澄,居然都是意外死亡地技,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,455評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門秒拔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來莫矗,“玉大人,你說我怎么就攤上這事砂缩∽餮瑁” “怎么了?”我有些...
    開封第一講書人閱讀 170,031評(píng)論 0 366
  • 文/不壞的土叔 我叫張陵庵芭,是天一觀的道長妹懒。 經(jīng)常有香客問我,道長双吆,這世上最難降的妖魔是什么眨唬? 我笑而不...
    開封第一講書人閱讀 60,334評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮好乐,結(jié)果婚禮上匾竿,老公的妹妹穿的比我還像新娘。我一直安慰自己曹宴,他們只是感情好搂橙,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,322評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著笛坦,像睡著了一般区转。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上版扩,一...
    開封第一講書人閱讀 52,895評(píng)論 1 314
  • 那天废离,我揣著相機(jī)與錄音,去河邊找鬼礁芦。 笑死蜻韭,一個(gè)胖子當(dāng)著我的面吹牛悼尾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播肖方,決...
    沈念sama閱讀 41,300評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼闺魏,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了俯画?” 一聲冷哼從身側(cè)響起析桥,我...
    開封第一講書人閱讀 40,264評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎艰垂,沒想到半個(gè)月后泡仗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,784評(píng)論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡猜憎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,870評(píng)論 3 343
  • 正文 我和宋清朗相戀三年娩怎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胰柑。...
    茶點(diǎn)故事閱讀 40,989評(píng)論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡截亦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出旦事,到底是詐尸還是另有隱情魁巩,我是刑警寧澤急灭,帶...
    沈念sama閱讀 36,649評(píng)論 5 351
  • 正文 年R本政府宣布姐浮,位于F島的核電站,受9級(jí)特大地震影響葬馋,放射性物質(zhì)發(fā)生泄漏卖鲤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,331評(píng)論 3 336
  • 文/蒙蒙 一畴嘶、第九天 我趴在偏房一處隱蔽的房頂上張望蛋逾。 院中可真熱鬧,春花似錦窗悯、人聲如沸区匣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,814評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽亏钩。三九已至,卻和暖如春欺旧,著一層夾襖步出監(jiān)牢的瞬間姑丑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,940評(píng)論 1 275
  • 我被黑心中介騙來泰國打工辞友, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留栅哀,地道東北人震肮。 一個(gè)月前我還...
    沈念sama閱讀 49,452評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像留拾,于是被迫代替她去往敵國和親戳晌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,995評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 他們說:生活是你擺脫不了痴柔,又一直在堅(jiān)持的躬厌。我不置可否,事情沒有絕對(duì)的對(duì)錯(cuò)竞帽,做好我現(xiàn)在做的扛施,同時(shí)又為想做的做好打算。...
    詩篇_8221閱讀 181評(píng)論 0 2
  • 一斷詞屹篓,一錯(cuò)字疙渣,一如往事逝 一葦渡來寒江釣,笑嘆風(fēng)來遲 一秋至堆巧,一衣織妄荔,一夜卷滿詩 一夢乍醒北窗亂,只道風(fēng)不癡
    北城月閱讀 377評(píng)論 0 3
  • 母親谍肤,這個(gè)讓我歡喜讓我躲的人啦租, 雖然寫的最多的是愛情,前幾年天天在說母愛的偉大荒揣,現(xiàn)在確感覺無人提起篷角, 誤以為...
    站在屋頂歌唱閱讀 131評(píng)論 0 0