Spring Ioc 源碼簡單梳理

Spring容器的refresh()【創(chuàng)建刷新】

prepareRefresh()

刷新前的預處理

  1. initPropertySource() 初始化一些屬性設置廷蓉,由子類自定義個性化的屬性設置
  2. getEnvironment().validateRequirProperties();檢查屬性的合法性,如一些必須要有的屬性是否存在
  3. earlyApplicationEvents=new LinkedHashSet<ApplicationEvent>()马昙;保存容器中的一些早期的事件

obtainFreshBeanFactory()

獲取BeanFactory;

  1. refreshBeanFactory();刷新【創(chuàng)建】BeanFactory;
    創(chuàng)建了一個this.beanFactory=new DefaultListableBeanFactory();
    對beanFactory設置序列化ID
    【Spring 5 會優(yōu)先判斷beanFactory是否存在桃犬,存在就先進行清空beanFactory包含里面的bean,并調(diào)用bean的銷毀方法行楞,再重新new一個 DefaultListableBeanFactory對象作為當前beanFactory】
  2. getBeanFactory();返回剛才GenericApplicationContext創(chuàng)建的BeanFactory對象攒暇;
  3. 將創(chuàng)建BeanFactory【DefaultListableBeanFactory】返回

prepareBeanFactory(beanFactory);

BeanFactory的預準備工作(BeanFactory進行一些設置)

  1. 設置BeanFactory的類加載器,支持表達式解析器...
  2. 添加部分BeanPostProcessor【ApplicationContextAwareProcessor】
  3. 設置忽略的自動裝配的接口EnvironmentAware,EmbeddedValueReslverAware,ResourceLoaderAware,ApplicationEventPublisherAware,MessageSourceAware,ApplicationContextAware,xxx;
  4. 注冊可以解析的自動裝配子房,我們能直接在任何組件中自動注入:BeanFactory,ResourceLoader,ApplicationEventPublisher,ApplicationContext
  5. 添加BeanPostProcessor【ApplicationListenerDetector】【ApplicationListenerDetector就是用于將實現(xiàn)ApplicationListener的bean添加到ApplicationContext中】
  6. 添加編譯時的AspectJ
  7. 給BeanFactory中注冊一些能用的組件:environment【ConfigurableEnvironment】,systemProperties【Map<String,Object>】,systemEnviroment【Map<String,Object>】

postProcessBeanFactory(beanFactory);

BeanFactory準備工作完成后進行的后置處理工作形用;

  1. 子類通過重新這個方法來在BeanFactory創(chuàng)建并預準備完成以后做進一步的設置

================================以上是BeanFactory的創(chuàng)建以預準備工作============================

invokeBeanFactoryPostProcessors(beanFactory)

執(zhí)行BeanFactoryProcessor;
BeanFactoryPostProcessor:BeanFactory的后置處理器。在BeanFactory標準初始化之后執(zhí)行的证杭;
兩個接口:BeanFactoryPostProcessor田度,BeanDefinitionRegistryPostProcessor:

  1. 執(zhí)行BeanFactoryPostProcessor方法
    先執(zhí)行BeanDefinitionRegistryPostProcessor:
    1.獲取所有的BeanDefinitionRegistryPostProcessor;
    2.看優(yōu)先級排序PriorityOrdered優(yōu)先級接口的BeanDefinitionRegistryPostProcessor;
    postProcessor.postProcessBeanDefinitonRegistry(registry)
    3.再執(zhí)行實現(xiàn)了Ordered順序接口的BeanDefinitionRegistryPostProcessor解愤;
    postProcessor.postProcessBeanDefinitonRegistry(registry)
    4.最后執(zhí)行沒有實現(xiàn)任何優(yōu)先級或是順序接口的BeanDefinitionRegistryPostProcessor;
    postProcessor.postProcessBeanDefinitonRegistry(registry)
    再執(zhí)行BeanFactoryPostProcessor
    1.獲取所有的BeanFactoryPostProcessor;
    2.看優(yōu)先級排序PriorityOrdered優(yōu)先級接口的BeanFactoryPostProcessor镇饺;
    postProcessor.postPorcessBeanFactory()
    3.再執(zhí)行實現(xiàn)了Ordered順序接口的BeanFactoryPostProcessor;
    postProcessor.postPorcessBeanFactory()
    4.最后執(zhí)行沒有實現(xiàn)任何優(yōu)先級或是順序接口的BeanFactoryPostProcessor;
    postProcessor.postPorcessBeanFactory()

registerBeanPostProcessors(beanFactory)

注冊BeanPostProcessor(Bean的后置處理器)【intercept bean creation.】
不同接口類型的BeanPostProcessor;在Bean創(chuàng)建前后的執(zhí)行時機是不一樣的
BeanPostProcessor送讲,
DestructionAwareBeanPostProcessor奸笤,
InstantiationAwareBeanPostProcessor惋啃,
SmartInstantiationAwareBeanPostProcessor,
MergedBeanDefinitionPostProcessor【該方法由internalPostProcessors】

  1. 獲取所有的BeanPostProcessor揭保;后置處理器都默認可以通過PriorityOrdered,Ordered接口來執(zhí)行優(yōu)先級
  2. 先注冊PriorityOrdered優(yōu)先級接口的BeanPostProcessor
    把每一個BeanPostProcessor肥橙;添加BeanFactory中
    beanFactory.addBeanPostProcessor(postProcessor)魄宏;
  3. 再注冊Ordered接口
  4. 最后注冊沒有實現(xiàn)任何優(yōu)先級接口的
  5. 最終注冊MergedBeanDefinitionPostProcessor秸侣;
  6. 注冊一個ApplicationListenerDetector來在Bean創(chuàng)建完成后檢查是否是ApplicationListener,如果是applicationContext.addApplicationListener(ApplicationListener<?>);

initMessageSource()

初始化MessageSource組件(做國際化功能;消息綁定宠互,消息解析)味榛;

  1. 獲取BeanFactory
  2. 看容器中是否有id為messageSource,類型是MessageSource的組件
    如果有賦值給messageSource予跌,如果沒有自己創(chuàng)建一個DelegatingMessageSource搏色;
    MessageSource:取出國際化配置文件中的某個key的值,能按照區(qū)域信息獲取
  3. 把創(chuàng)建好的MessageSource注冊在容器中券册,以后獲取國際化配置文件的時候频轿,可以自動注入MessageSource,然后調(diào)用它的getMessage方法實現(xiàn)國際化功能
    beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME,this.messageSource);

initApplicationEventMulticaster()

初始化事件派發(fā)器

  1. 獲取BeanFactory
  2. 從BeanFactory中獲取applicationEventMulticaster
  3. 如果上一步?jīng)]有配置烁焙;創(chuàng)建一個SimpleApplicationEventMulticaster
  4. 將創(chuàng)建的ApplcaitionEventMulticaster添加到BeanFactory中航邢,以后其他組件自動注入

onResfresh()

留給子容器(子類)

  1. 子類重寫這個方法,在容器刷新的時候可以自定義邏輯

regsisterListeners()

給容器中將所有項目里面的ApplicationListener注冊進來骄蝇;

  1. 從容器中拿到所有的ApplicationListener
  2. 將每個監(jiān)聽器添加到事件派發(fā)器中
    getApplicationEventMulticaster().addApplicationListenerBean(listener);
  3. 派發(fā)之前步驟產(chǎn)生的事件:

finsihBeanFactoryInitialization(beanFactory)

初始化所有剩下的單實例bean

  1. beanFactory.preInstantiateSingletons();初始化后剩下的單實例bean膳殷;
    1. 獲取容器中的所有bean,依次進行初始化和創(chuàng)建對象
    2. 獲取bean的定義信息:RootBeanDefinition
    3. Bean不是抽象的九火,是單實例的赚窃,不是懶加載:
      1. 判斷是否是FactoryBean,是否是實現(xiàn)FactoryBean接口的Bean
      2. 不是工廠Bean。利用getBean(beanName)岔激;創(chuàng)建對象
        1. getBean(beanName);ioc.getBean();
        2. doGetBean(name,null,null,false);
        3. 先獲取緩存中保存的單例Bean勒极。如果能獲取到說明這個bean之前被創(chuàng)建過(所有創(chuàng)建過的單實例bean都會被緩存起來)
          從private final Map<String,Object> singletonObjects=new ConcurrentHashMap<>()獲取
        4. 緩存中獲取不到,開始Bean的創(chuàng)建對象流程
        5. 標記當前bean已經(jīng)被創(chuàng)建
        6. 獲取bean的定義信息
        7. 獲取當前bean依賴的其他bean虑鼎;如果按照getBean()把依賴的bean先創(chuàng)建出來辱匿。
        8. 啟動單實例bean的創(chuàng)建流程:
          1. createBean(bean,rootBeanDefinition,args);
          2. Object bean=resolveBeforeInstantiation(beanName,mbdToUser);讓BeanPostProcess先嘗試創(chuàng)建代理對象
            InstantiationAwareBeanPostProcessor:提前執(zhí)行
            先觸發(fā):postProcessBefroeInstantiation();
            如果有返回值:觸發(fā)postProcessAfterInitialization();
          3. 如果前面的InstantiationAwareBeanPostProcessor沒有返回代理對象:
          4. Object beanInstance=doCreateBean(beanName,mbdToUse,args);
            1. 創(chuàng)建Bean實例,createBeanInstance(beanName,rootBeanDefinition,args);
              利用工廠方法或者對象的構造器創(chuàng)建出Bean的實例
            2. applyMergedBeanDefinitionPostProcessor(rootBeanDefinition,beanType,beanName);
              調(diào)用MergedBeanDefinitionPostPorcessor的postProcessMergedBeanDefinition方法。
            3. 【Bean屬性賦值】populateBean(beanName,beanDefinition,instanceWrapper);
              1.拿到InstantiationAwareBeanPostProcessor后置處理器:postProcessAfterInstantiation();
              2.拿到InstantiationAwareBeanPostProcessor后置處理器:
              postProcessPropertyValues();
              1. 應用Bean屬性的值;為屬性利用setter方法等進行賦值:applyPropertyValues(beanName,beanDefinition,beanWrapper,propertyValues);
            4. 【Bean初始化】initializeBean(beanName,exposedObject,beanDefinition);
              1. 【執(zhí)行Aware接口方法】invokeAwareMethods(beanName,bean);執(zhí)行xxxAware接口方法:BeanNameAware\BeanClassLoaderAware\BeanFactoryAware
              2. 【執(zhí)行后置處理器】:applyBeanPostProcessorsBeforeInsitalization(wrappedBean,beanName)
                BeanPostProcessor.postProcessBeforeInitiaization()
              3. 【執(zhí)行初始化方法】invokeInitMethods(beanName,wrappedName,beanDefinition);
                1. 是否是InitializingBean接口實現(xiàn)计维;執(zhí)行接口規(guī)定的初始化
                2.是否自定義初始化方法霜医;
              4. 【執(zhí)行后置處理器初始化之后】applyBeanPostProcessorsAfterInitalization
                BeanPostProcessor.postProcessAfterInitiaization()
              5. 注冊Beande銷毀方法
          5. 將創(chuàng)建的Bean添加到緩存中singletonObjects;
            ioc容器就是這個Map,很多的Map里面保存了單實例Bean霉旗,環(huán)境信息..
            所有Bean都利用genBean創(chuàng)建完成以后;
            檢查所有Bean是否是SmartInitializingSingleton接口;如果是扔嵌,就執(zhí)行afterSingletonsInstantiation

finishRefresh()

完成BeanFactory的初始化創(chuàng)建工作限府,IOC容器就創(chuàng)建完成;

  1. initLifecycleProcessor();初始化和生命周期有關的后置處理器痢缎;LifecycleProessor.
    默認從容器中找是否有l(wèi)ifecycleProcessor的組件【LifecycleProessor】;如果沒有new DefaultLifecycleProcessor,并加入都容器中胁勺。
    實現(xiàn)一個LifecycleProcessor類,beanFactory在此方法回調(diào)LifecycleProcessor的onRefresh()方法独旷,當beanFactory銷毀時候署穗,會回調(diào)onClose()方法;
  2. getLifecycleProcessor().onRefresh();
    拿到前面定義的生命周期處理器(beanFactory);回調(diào)onRefresh();
  3. publishEvent(new ContextRefreshedEvent(this));發(fā)布容器刷新完成事件
  4. liveBeanView.regsiterApplicationContext(this);

總結

  1. Spring容器在啟動的時候嵌洼,先會保存所有注冊進來的Bean定義信息
    1. xml注冊bean:<bean>
    2. 注解注冊Bean:@Service案疲,@Component,@Bean
  2. Spring容器會合適的時機創(chuàng)建這些Bean
    1. 用到這個bean的時候麻养;利用genBean創(chuàng)建bean褐啡;創(chuàng)建好以后保存在容器中;
    2. 統(tǒng)一創(chuàng)建剩下所有的bean的時候鳖昌;finishBeanFactoryInitialization();
  3. 后置處理器
    每一個bean創(chuàng)建完成备畦,都會使用各種后置處理進行處理;來增強bean的功能许昨;
    AutowiredAnntationBeanPortProcessor:處理自動注入
    AnnotationAwareAspectJAutoProxyCreate:來做AOP功能懂盐;
    xxx...
    增強的功能注解
    AsyncAnnotationBeanProcessor
    ......
  4. 事件驅動模型:
    ApplicationListener:事件監(jiān)聽;
    ApplicationEventMulticaster:事件派發(fā)车要;
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末允粤,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子翼岁,更是在濱河造成了極大的恐慌类垫,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件琅坡,死亡現(xiàn)場離奇詭異悉患,居然都是意外死亡,警方通過查閱死者的電腦和手機榆俺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門售躁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人茴晋,你說我怎么就攤上這事陪捷。” “怎么了诺擅?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵市袖,是天一觀的道長。 經(jīng)常有香客問我烁涌,道長苍碟,這世上最難降的妖魔是什么酒觅? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮微峰,結果婚禮上舷丹,老公的妹妹穿的比我還像新娘。我一直安慰自己蜓肆,他們只是感情好颜凯,可當我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著症杏,像睡著了一般装获。 火紅的嫁衣襯著肌膚如雪瑞信。 梳的紋絲不亂的頭發(fā)上厉颤,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天,我揣著相機與錄音凡简,去河邊找鬼逼友。 笑死,一個胖子當著我的面吹牛秤涩,可吹牛的內(nèi)容都是我干的帜乞。 我是一名探鬼主播,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼筐眷,長吁一口氣:“原來是場噩夢啊……” “哼黎烈!你這毒婦竟也來了?” 一聲冷哼從身側響起匀谣,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤照棋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后武翎,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體烈炭,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年宝恶,在試婚紗的時候發(fā)現(xiàn)自己被綠了符隙。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡垫毙,死狀恐怖霹疫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情综芥,我是刑警寧澤丽蝎,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站毫痕,受9級特大地震影響征峦,放射性物質發(fā)生泄漏迟几。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一栏笆、第九天 我趴在偏房一處隱蔽的房頂上張望类腮。 院中可真熱鬧,春花似錦蛉加、人聲如沸蚜枢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽厂抽。三九已至,卻和暖如春丁眼,著一層夾襖步出監(jiān)牢的瞬間筷凤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工苞七, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留藐守,地道東北人。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓蹂风,卻偏偏與公主長得像卢厂,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子惠啄,可洞房花燭夜當晚...
    茶點故事閱讀 45,685評論 2 360

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