08spring源碼分析-注解驅(qū)動如何實現(xiàn)

Spring注解源碼分析

我們知道如果想使用spring注解你需要在applicationContext.xml配置文件中設(shè)置context:component-scan base-package='xxx'這樣spring會幫助我們掃描你所設(shè)置的目錄里面所有的Bean外潜,如果Bean上面有相應(yīng)的@Service,@Controller注解(當然還有其他的撤防,這里就不一一列出來)弥喉,那么Spring的IOC容器將會幫我實例對象戴涝,設(shè)置屬性洪唐。

分析spring如果實現(xiàn)注解驅(qū)動

還是從spring配置文件的命名空間入手谐鼎,不清楚的可以參考我之前的文章唯咬。找到spring-context包進入文件里面找到src/main/resources/META-INF/spring.handlers這樣你可以看到一下內(nèi)容:

http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler
http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler
http\://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler
http\://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler

可以看到context命名空間解析的類org.springframework.context.config.ContextNamespaceHandler所以可以直接定位到spring掃描的過程席楚。

spring源碼分析-ContextNamespaceHandler

//組件掃描
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());

整個掃描包路徑的過程如下:

  • 取出自定義base-package路徑

  • 創(chuàng)建ClassPathBeanDefinitionScanner對象并且設(shè)置springIOC容器所關(guān)心的注解@Component換言之:只要類定義上面有@Component注解那么我們的掃描器就需要處理這個類咬崔。

    • 設(shè)置BeanName生成工具(這里是生成類名的工具有默認的beanName,也有自定義@Service("abc"))
  • 開始掃描包烦秩,使用ClassReader掃描所有類可以得到類的信息垮斯,對比是否有@Component注解,如果有生成BeanDefinition=ScannedGenericBeanDefinition

  • 注冊Spring內(nèi)置的BeanPostProcessor對象只祠。默認有8個org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)主要需要注意的有四個

    • ConfigurationClassPostProcessor:處理配置類
    • AutowiredAnnotationBeanPostProcessor:處理@Autowired幫助類注入屬性
    • RequiredAnnotationBeanPostProcessor:處理@required
    • CommonAnnotationBeanPostProcessor:處理@Resource幫助類注入屬性
    • 入口代碼:
        if (annotationConfig) {
      //這里會注冊很多內(nèi)容BeanPostProcessor類
            Set<BeanDefinitionHolder> processorDefinitions =AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);
            for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
                compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));
            }
        }

上面只是注冊了所有內(nèi)置Annotation工具類兜蠕,還沒有實例化。接下來我們要進入refresh()方法看看基于注解的類實例化過程

注解類實例過程

在前面基于注解的類已經(jīng)被掃描成為ScannedGenericBeanDefinition現(xiàn)在就要實例化了抛寝。再refresh()方法中首先需要注冊前面說的內(nèi)置處理Annotation類的工具類熊杨,沒錯就是這幾個:

2 = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"
3 = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"
4 = "org.springframework.context.annotation.internalRequiredAnnotationProcessor"
5 = "org.springframework.context.annotation.internalCommonAnnotationProcessor"
6 = "org.springframework.context.event.internalEventListenerProcessor"
7 = "org.springframework.context.event.internalEventListenerFactory"
//最終這些類變?yōu)椋?0 = {ApplicationContextAwareProcessor@1792} 
1 = {ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor@1961} 
2 = {PostProcessorRegistrationDelegate$BeanPostProcessorChecker@2193} 
3 = {CommonAnnotationBeanPostProcessor@2135} 
4 = {AutowiredAnnotationBeanPostProcessor@1991} 
5 = {RequiredAnnotationBeanPostProcessor@2107} 
6 = {ApplicationListenerDetector@2194} 

入口在:registerBeanPostProcessors(beanFactory);這里會將上面的類注冊到IOC容器中,然后根據(jù)Bean的生命周期中的第6步設(shè)置屬性墩剖,依據(jù)Annotation的方式注入屬性:CommonAnnotationBeanPostProcessor來處理屬性的注入猴凹。我們使用了@Resource來配置屬性。

整個實例的全流程可以參考另一篇文章

07spring源碼分析-從Bean的生命周期分析IOC創(chuàng)建對象過程

//TODO 學習ClassReader對象
classReader
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末岭皂,一起剝皮案震驚了整個濱河市郊霎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌爷绘,老刑警劉巖书劝,帶你破解...
    沈念sama閱讀 212,332評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異土至,居然都是意外死亡购对,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,508評論 3 385
  • 文/潘曉璐 我一進店門陶因,熙熙樓的掌柜王于貴愁眉苦臉地迎上來骡苞,“玉大人,你說我怎么就攤上這事〗庥模” “怎么了贴见?”我有些...
    開封第一講書人閱讀 157,812評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長躲株。 經(jīng)常有香客問我片部,道長,這世上最難降的妖魔是什么霜定? 我笑而不...
    開封第一講書人閱讀 56,607評論 1 284
  • 正文 為了忘掉前任档悠,我火速辦了婚禮,結(jié)果婚禮上望浩,老公的妹妹穿的比我還像新娘辖所。我一直安慰自己,他們只是感情好磨德,可當我...
    茶點故事閱讀 65,728評論 6 386
  • 文/花漫 我一把揭開白布奴烙。 她就那樣靜靜地躺著,像睡著了一般剖张。 火紅的嫁衣襯著肌膚如雪切诀。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,919評論 1 290
  • 那天搔弄,我揣著相機與錄音幅虑,去河邊找鬼。 笑死顾犹,一個胖子當著我的面吹牛倒庵,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播炫刷,決...
    沈念sama閱讀 39,071評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼擎宝,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了浑玛?” 一聲冷哼從身側(cè)響起绍申,我...
    開封第一講書人閱讀 37,802評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎顾彰,沒想到半個月后极阅,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,256評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡涨享,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,576評論 2 327
  • 正文 我和宋清朗相戀三年筋搏,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片厕隧。...
    茶點故事閱讀 38,712評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡奔脐,死狀恐怖俄周,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情髓迎,我是刑警寧澤栈源,帶...
    沈念sama閱讀 34,389評論 4 332
  • 正文 年R本政府宣布,位于F島的核電站竖般,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏茶鹃。R本人自食惡果不足惜涣雕,卻給世界環(huán)境...
    茶點故事閱讀 40,032評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望闭翩。 院中可真熱鬧挣郭,春花似錦、人聲如沸疗韵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蕉汪。三九已至流译,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間者疤,已是汗流浹背福澡。 一陣腳步聲響...
    開封第一講書人閱讀 32,026評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留驹马,地道東北人革砸。 一個月前我還...
    沈念sama閱讀 46,473評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像糯累,于是被迫代替她去往敵國和親算利。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,606評論 2 350

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

  • | 題記昨天是我的老單位深圳電臺開播三十周年的紀念慶典,早已不是圈內(nèi)人的我自然未能躬逢盛會胖秒,但舊同僚朋友圈的不斷刷...
    柳七歸來閱讀 538評論 0 0
  • 昨夜忽起感慨允耿,寫了一段流心的文字,“人啊扒怖,從來都只是會被自己在乎的東西傷害较锡。”盗痒、“這愛恨煎熬蚂蕴,得失過后低散,不經(jīng)意便是...
    化濁閱讀 268評論 0 2
  • 年華易逝熔号,不知不覺間,步入了老年鸟整。 人活這一輩子引镊,年輕的時候追求成功和榮譽,來證明自己的價值篮条。年老了弟头,就跟隨自己的...
    雨天_7afd閱讀 281評論 0 11