圖1
上次看到doRegisterBeanDefinitions方法,是DefaultBeanDefinitionDocumentReader這個類,這里是真正開始解析xml。
那么先來看下doRegisterBeanDefinitions做了些什么,先調用了createDelegate方法,如圖2:
圖2
實例化了一個BeanDefinitionParserDelegate(這里用了代理模式,不知道對不對),在來看下initDefaults方法,如圖3:
圖3
能看到有個populateDefaults方法,defaults全局變量是DocumentDefaultsDefinition defaults = new DocumentDefaultsDefinition();這個類包含了最外層<beans>的一些屬性,關鍵還是看下populateDefaults方法,如圖4:
圖4
方法太長用兩張截圖

這里是解析最外層的<beans>的一些屬性,一共有6個:
- default-lazy-init:延遲加載,延遲實例化bean;
- default-merge:在繼承關系時在子類中合並父類的值;
- default-autowire:按哪種方式注入,byType、byName等;
- default-autowire-candidates:匹配到的bean才能加載;
- default-init-method:初始化方法;
- default-destroy-method:銷毀方法;
能看到最后有一個setSource方法,這個可以自己實現SourceExtractor,額外的source信息,通過XmlBeanDefinitionReader.setSourceExtractor(SourceExtractor);來實現。如圖5:
圖5

使用的話如圖6:
圖6

好了那么繼續下看,在解析完這些屬性以后,有個this.readerContext.fireDefaultsRegistered(this.defaults);方法,如圖7:
圖7

這里有個eventListener,默認是EmptyReaderEventListener,可以自己實現ReaderEventListener以后覆蓋掉,具體用法和SourceExtractor是一樣的,這里不再累述了。
那創建完代理類就是真正的解析啦,就是parseBeanDefinitions(root, this.delegate);方法,如圖8:
圖8

關於自定義標簽我們下次再講,還是來看下parseDefaultElement(ele, delegate);方法把,如圖9:
圖9

很明確就是解析四個標簽:<import>、<bean>、<aliias>、<beans>,先來看下在復雜也最繁瑣的解析<bean>吧,如圖10:
圖10

這個方法就是處理<bean>解析並完成注冊的方法,代理方法開始顯威啦delegate.parseBeanDefinitionElement(ele);如圖11:
圖11

能看到先取id和name,默認的bean name是id,但是如果id沒有,name就是bean name,在配置中name還可以用",; "分隔開,一個bean可以擁有多個別名,最后別名放到哪里我們后面會看到,如圖12:
圖12

剛只是方法的前半部分,還有后半部分,如圖13:
圖13

parseBeanDefinitionElement(ele, beanName, containingBean);方法就是解析<bean>中的所有屬性,如圖14:
圖14

這是方法的前半部分,其實沒啥好看的,關鍵還得看后半部分,如圖15:
圖15

這里就是解析<bean>里面所有的attribute了,具體這里就不在往下挖了因為實在太多了,最后所有解析出來的值都放入了AbstractBeanDefinition類中,好奇的小伙伴肯定想<bean>里面到底有多少屬性,這里來列一下:
- scope
- abstract
- lazy-init
- autowire
- depends-on
- autowire-candidate
- primary
- init-method
- destroy-method
- factory-method
- factory-bean
具體怎么使用請看官網。
那么好了bean的所有信息都拿到了,接下去干嘛呢,回過頭看圖13,如果沒有定義beanName的話,只有class,這個時候會去生成一個beanName,類似於com.shenqi.test.abc#0,如果有第二個就是#1這樣以此類推。好,那么這個時候就返回了一個BeanDefinitionHolder,回過頭來看圖10的BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());方法,如圖16:
圖16

拿到了beanName,最后放入到DefaultListableBeanFactory,BeanDefinition放入Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);,beanName放入private volatile List<String> beanDefinitionNames = new ArrayList<>(256);中,別名的話會放入SimpleAliasRegistry的private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);中。
那么關於解析<alias>的話,其實最后就是放入SimpleAliasRegistry的private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);中。
<import>其實就是把讀取xml和解析xml重新走一遍。
內嵌的<beans>的話就是解析圖8的parseBeanDefinitions(root, this.delegate);重新走一遍。
這次一些細節的地方沒有說明,大家可以自行去研究下,比如<meta>做獲取,lookup,<qualifier>怎么使用等。
下次的話就是自定義啦。
如有問題請提出,共同提高,謝謝!!