Spring 源碼學習 05:BeanDefinition 概念及其實現

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"前言","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"BeanDefinition:顧名思義,就是 Bean 的定義,是用來描述一個 Bean 都有什麼信息。前面說在初始化 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"DefaultListableBeanFactory","attrs":{}}],"attrs":{}},{"type":"text","text":" 時,會初始化一個 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Map","attrs":{}}],"attrs":{}},{"type":"text","text":",這個 Map 的功能暫且不說,(PS:查資料說的是存儲 bean),所以今天就結合官方文檔以及源碼,一起了解一下 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"BeanDefinition","attrs":{}}],"attrs":{}},{"type":"text","text":"!","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"概念","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/b7/b78e503009476f65e469e242f3bbe4cc.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在容器內部,使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"BeanDefinition","attrs":{}}],"attrs":{}},{"type":"text","text":" 對象定義一個 Bean。而定義的信息包含 類名、作用域、是否懶加載、構造參數、初始化方法、銷燬方式等等。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"瞭解了概念之後,開始閱讀源碼,源碼部分比較長。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"源碼介紹","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/32/322fa58513d92cfee956850a8986a2ec.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過 UML 可以看出 BeanDefinition 接口繼承了 AttributeAccessor 和 BeanMetadataElement 兩個接口。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"AttributeAccessor","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"AttributeAccessor:定義用於將元數據附加到任意對象或從任意對象訪問元數據的通用協定的接口。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public interface AttributeAccessor {\n\n\tvoid setAttribute(String name, @Nullable Object value);\n\n\t@Nullable\n\tObject getAttribute(String name);\n\n\t@Nullable\n\tObject removeAttribute(String name);\n\n\tboolean hasAttribute(String name);\n\n\tString[] attributeNames();\n}","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過接口方法可以看出,AttributeAccessor 主要定義了對元數據","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"屬性","attrs":{}}],"attrs":{}},{"type":"text","text":"的增刪改查。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/50/507f6b1a0aedd904b5f2dc20a55f0548.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"AttributeAccessorSupport","attrs":{}}],"attrs":{}},{"type":"text","text":" 是 AttributeAccessor 接口的一個實現,通過實現可以看出,其內部使用了 Map 保存名稱和屬性值。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"BeanMetadataElement","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"BeanMetadataElement:由包含配置源對象的 bean 元數據元素實現的接口。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public interface BeanMetadataElement {\n\t@Nullable\n\tdefault Object getSource() {\n\t\treturn null;\n\t}\n}","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接口內部只有一個 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"getSource()","attrs":{}}],"attrs":{}},{"type":"text","text":" 方法,其含義爲:","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"返回此元數據元素的配置源Object (可以爲null )。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其實還是不知道啥意思……","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在子類(","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"BeanMetadataAttributeAccessor","attrs":{}}],"attrs":{}},{"type":"text","text":")中加上斷點,debug","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/fa/fa851062e6c097da58c7c6cae7fa7feb.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏 source 裏面存儲了 Class 類文件在磁盤的真實路徑。當然姑且可以這麼認爲,畢竟我這也是剛開始學習源碼,當前的結論只是 debug 到的,也有可能在別的實現類中存儲的是別的信息。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"BeanDefinition","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"BeanDefinition 方法較多,就不貼代碼,或者截圖了。詳細可以通過 ","attrs":{}},{"type":"link","attrs":{"href":"https://github.com/liuzhihang/spring-framework/blob/master/spring-beans/src/main/java/org/springframework/beans/factory/config/BeanDefinition.java","title":""},"content":[{"type":"text","text":"我的 GitHub","attrs":{}}]},{"type":"text","text":" 進行閱讀,上面添加了相關注釋。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不過還是簡要介紹一下方法,大概有 Bean 的名字、作用範圍、是否首選、以及 Bean 的初始化銷燬方法等等。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"BeanDefinition 只是一個接口,其實現又分爲好幾種。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/9a/9a3b1ac98ffc9e40931d4c549bf97f89.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"AbstractBeanDefinition ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"AbstractBeanDefinition 作爲 BeanDefinition 的抽象實現類,內部定義了很多屬性,以滿足 BeanDefinition 定義的接口功能。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/02/0246f90c392d26129b57a2db8134d219.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這些屬性的操作,就對應着 BeanDefinition 定義的接口方法。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"AbstractBeanDefinition 的三個實現類","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"AbstractBeanDefinition 的實現又分爲三個:分別是 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ChildBeanDefinition","attrs":{}}],"attrs":{}},{"type":"text","text":"、 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"RootBeanDefinition","attrs":{}}],"attrs":{}},{"type":"text","text":"、 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"GenericBeanDefinition","attrs":{}}],"attrs":{}},{"type":"text","text":"。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"ChildBeanDefinition:可以從 Parent Definition 裏面繼承一些公共定義(初始化方法、銷燬方法、是否懶加載等等)不過","attrs":{}}]}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"2","normalizeStart":"2"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"RootBeanDefinition:定義 Bean Definition 的公共屬性,該定義在運行時支持Spring BeanFactory中的特定bean。 而 RootBeanDefinition 是不可以設置 parentName 指定 Parent Definition 的。","attrs":{}}]}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"3","normalizeStart":"3"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"GenericBeanDefinition:是一個通用的 Bean Definition,是一站式服務,用於標準bean定義。 像任何bean定義一樣,它允許指定一個類以及可選的構造函數參數值和屬性值。 另外,可以通過 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"parentName","attrs":{}}],"attrs":{}},{"type":"text","text":" 屬性靈活地配置從父bean定義派生的內容。所以現在一般使用 GenericBeanDefinition。","attrs":{}}]}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從 Spring 2.5 開始,以編程方式註冊 Bean Definition 的首選方法是 GenericBeanDefinition 類,該類允許通過 GenericBeanDefinition.setParentName 方法動態定義父依賴項。 ","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"GenericBeanDefinition 下面還有兩個實現:","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ScannedGenericBeanDefinition","attrs":{}}],"attrs":{}},{"type":"text","text":" 、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"AnnotatedGenericBeanDefinition","attrs":{}}],"attrs":{}},{"type":"text","text":"。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/31/315aab751d62e4d9b89166f7cfd63f04.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"二者並無太大區別,只不過 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"AnnotatedGenericBeanDefinition","attrs":{}}],"attrs":{}},{"type":"text","text":" 比 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ScannedGenericBeanDefinition","attrs":{}}],"attrs":{}},{"type":"text","text":" 多了一個 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"factoryMethodMetadata","attrs":{}}],"attrs":{}},{"type":"text","text":" 的定義。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"總結","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過閱讀 BeanDefinition 的源碼,並對其實現類的源碼進行閱讀之後,大致瞭解 BeanDefinition 的概念及其含義。大概作圖總結如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/b1/b150264a286b67afa9cf3f6a3b06a714.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"相關推薦","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/s/JwRsKHqJ0ZcJ6Cgbp5BKiw","title":""},"content":[{"type":"text","text":"Spring 源碼學習 04:初始化容器與 DefaultListableBeanFactory","attrs":{}}]}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/s/V7SjmIFKAXyppBF_KHbxXQ","title":""},"content":[{"type":"text","text":"Spring 源碼學習 03:創建 IoC 容器的幾種方式","attrs":{}}]}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/s/YPDPU7ePtii0vlrynexb_w","title":""},"content":[{"type":"text","text":"Spring 源碼學習 02:關於 Spring IoC 和 Bean 的概念","attrs":{}}]}]}],"attrs":{}}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章