Spring-beans的核心實體是BeanDefinition和BeanFactory。前者映射咱們的定義,後者則是依據定義生產bean的工廠。
上圖是spring beans的靜態結構圖,更可能是偏重於bean解析,由於1. 理解了bean解析也就理解了一半spring擴展能力;2.BeanFactory的複雜不在於類之間的組織結構,而在於複雜的調用鏈路,也就不必是靜態結構方面作過多說明。須要說明的是,這只是概念模型,並不徹底映射到類,由於spring的抽象層次過高,一個概念實體功能每每由多個類協同完成,畫起來比較費勁,就相似BeanFactory,光搞清楚各個BeanFactory之間的關係就理得頭痛,因此都儘量從概念層面說明。css
重要實體說明
- DefaultListableBeanFactory是BeanDefintionRegistry的默認實現,它是個適配器,用於適配BeanFactory和BeanDefintionRegistry,工廠和定義經過它統一。它由ApplicationContext初始化,並被做爲BeanDefinitionReader的registry。Reader對配置文檔加載解析,生成definition並註冊到registry–其實就是DefaultListableBeanFactory,這樣工廠就擁有了類定義,bean初始化時也能夠經過內部方法輕鬆獲取到定義。
- NamespaceHandlerResolver用於獲取配置解析實體–NamespaceHandler。它和registry均內聚在上下文實體–ReaderContext中,parser內聚上下文從而能夠間接訪問handler和registry得到解析和註冊的能力。
其餘幾個實體都比較直觀便於理解,再也不一一贅述。spring
總體交互過程
BeanDefinitionReader是整個bean解析的聚合根,它由ApplicationContext建立,並將DefaultListableBeanFactory做爲registry傳遞給它。
BeanDefinitionReader建立文檔讀取實體–DocuemntReader用於加載解析,並在step3加載文檔時建立上下文–ReaderContext傳遞給文檔讀取實體。上下文貫穿於整個解析過程始終,它在文檔讀取實體使用parser解析時也會被傳入parser中。mvc
Parse過程是整個加載過程的核心,默認parser經過間接關聯的識別器能夠依據不一樣配置節點進行parser切換,當讀到非默認配置時,則切換到對應客戶化parser解析。解析完成後再經過間接關聯的registry進行註冊,從而配置定義進入spring管理,待getBean時使用。app
客戶化配置節點解析
客戶化配置是spring很是重要的擴展點,spring強大的擴展能力有一半功能要歸功於它,另外一半中的80%就是後面要介紹的大名鼎鼎的BeanPostProcessor。不只僅一些第三方擴展(例如開篇提到的dubbo)基於它,spring自己的不少模塊也是基於它,例如spring-aop,spring-context等等,spring體系內除了默認的beans命名空間其他都基於它擴展的。jvm
NamespaceHandlerResolver由BeanDefinitionReader初始化,後者在第一次被訪問時讀取spring.handlers文件。.handlers文件定義namespace uri和對應處理類的映射關係。例如:spa
http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
上面的這行配置就是配置聲明的解析類。代理
NamespaceHandlerResolver依據節點namespace得到NamespaceHandler,而後使用handler處理自定義配置節點。code
public interface NamespaceHandler { void init(); BeanDefinition parse(Element element, ParserContext parserContext); BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder definition, ParserContext parserContext); }
init方法註冊localName和自定義parser的關係,parser和localName的關係由handler的提供者本身註冊。例如:繼承
public void init() { // In 2.0 XSD as well as in 2.1 XSD. registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser()); registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser()); registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator()); // Only in 2.0 XSD: moved to context namespace as of 2.1 registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); }
上面就是aop註冊parser的代碼片斷。config,aspectj-autoproxy這些就是localName,parse過程當中不一樣的localName會切換到不一樣的parser解析。接口
spring先經過命名空間定位到handler,handler處理時再基於localName取相應的parser解析當前結點。好比這個配置,aop是命名空間,aspectj-autoproxy是localName。整個讀取解析過程當中先經過aop找到AopNamespaceHandler,再在解析到aspectj-autoproxy節點時使用AspectJAutoProxyBeanDefinitionParser來解析。若是要研究spring源碼,必定要先找到對應parser,知道每一個配置項對應到運行時的bean結構才能更好理解spring;並且parser可能會生成一些默認的BeanPostProcessor,若是意識不到這些後處理器,那麼對代碼的讀取將會斷片,陷入徹底沒法理解的境地。好比spring-aop就是由parser默認生成AopAutoProxyCreator這個BeanPostProcessor,在bean初始化後由這個processor對bean生成代理。
Bean獲取
上圖是getBean過程,整個過程很簡潔,實際深刻代碼會發現很是繁瑣。
BeanFactory和BeanDefinitionRegistry在spring裏是統一的,參見第一節,圖上爲了方便理解,拆成兩個概念實體。
須要注意的是第4步和第6步,bean配置時能夠指定parent屬性,若是有parent,則beanFactory會對local和parent作merge,merge的策略是對parent作覆蓋,也能夠理解爲是對parent作繼承。這和parent bean factory徹底是兩個概念,必定要區分開。
在beans的實體靜態結構裏,分別註明了parent bean definition和parent bean factory。二者都是被關聯的,而不是被繼承。後者有點像jvm的雙親委託模型,parent和child有各自的上下文,相似於jvm的命名空間。parent bean factory由applicationContext設置,沒法配置。好比spring mvc就是兩個父子兩個容器,在容器refresh時相應的也會把父容器的BeanFactory設置成子容器BeanFactory的parentBeanFactory。
spring bean狀態
Bean主要通過instantiate,populate,initializeBean和registerDisposableBean4個狀態,在狀態流轉中會調用不少spring預留的擴展接口。
-
awareMethod
若是bean繼承了BeanFactoryAware,BeanNameAware,BeanClassLoaderAware,則會在initialize階段將BeanFactory, BeanName和bean ClassLoader設置給Bean。
注意它和ApplicationContextAware是不同的,後者是由BeanPostProcessor作後處理set的。 -
init method init method不只僅包括配置的init-method方法還包括InitializedBean的afterPropertiesSet回調接口,這二者均是無參的,徹底能夠互相替代,二者中afterPropertiesSet調用在前。