規範命名,有助於思想的傳承。
最近在閱讀Spring的過程當中,發現除了 AOP,IOC以外,還有許多被忽略的有助於閱讀/理解源碼的點,在此一一作筆記,供人蔘閱,但願有所幫助。若有錯漏,但願可以指出以便修正,不勝感激。web
Spring 的源碼中,核心類的命名與功能劃分具備必定的規範,瞭解後,在閱讀Spring源碼中,有些許的幫助。spa
Spring底層核心類,不少接口是按照冪等與非冪等/讀寫分離進行劃分的:
BeanFactory:內部方法均爲獲取或者判斷的方法,如:getBean
,containsBean
等;
ConfigurableBeanFactory:繼承了BeanFactory
後,內部定義了屬性設置的入口,非冪等的,如:setParentBeanFactory
,setConversionService
Environment:內部方法均爲獲取,或者判斷的方法,如:containsProperty
,getActiveProfiles
;
ConfigurableEnvironment:繼承了Environment
後,內部方法定義的是設置方法,非冪等的,如:setActiveProfiles
,merge
;code
Spring 的 接口定義中,接口的命名有其規範性存在, 單純的冪等性方法,直接按實際做用命名(主要爲冪等性), 非冪等性,則在實際做用命名前(繼承了冪等性類),增長 `Configurable`, 基礎實現,則在非冪等性的基礎上(繼承了非冪等性類),對方法進行通用的基礎實現
Environment:擁有獲取 property
,profile
的方法
ConfigurableEnvironment:擁有setActiveProfiles
等方法
AbstractEnvironment:對以上兩個類方法進行基礎實現orm
ApplicationContext:擁有獲取 ID
,BeanFactory
等方法,如:getApplicationName
,getParent
,getAutowireCapableBeanFactory
ConfigurableApplicationContext:擁有設置對應屬性的方法,如:setEnvironment
,setParent
AbstractApplicationContext:對上述兩個類方法進行基礎實現xml
PropertyResolver:獲取屬性的方法,如:getProperty
,containsProperty
ConfigurablePropertyResolver:設置性的方法,如:setConversionService
,setPlaceholderPrefix
AbstractPropertyResolver:對以上兩個類方法繼續基礎實現繼承
PropertyAccessor:屬性的判斷及獲取
ConfigurablePropertyAccessor:屬性的設置
AbstractPropertyAccessor:基本實現遞歸
針對向某個 Collection 中添加/註冊某個實例,Spring 經常使用的命名方式是使用 Registry 做爲後綴,就實際功能而言,這些類是將對應實例歸入Spring容器管理的入口!
ConverterRegistry:轉換器註冊器,提供了 addConverter
,addConverterFactory
等方法
AliasRegistry:別名註冊器,registerAlias
,removeAlias
,isAlias
,getAliases
BeanDefinitionRegistry:Bean定義註冊器,提供了registerBeanDefinition
,removeBeanDefinition
SingletonBeanRegistry:單例註冊器,方法:registerSingleton
,containsSingleton
接口
默認實現,在Abstract***以後,使用了Default前綴
如:DefaultConversionService
,DefaultListableBeanFactory
,DefaultNamespaceHandlerResolver
資源
當一個類有層級概念(代表該類在處理時須要考慮父級狀況)時,會定義一個前綴:`HierarchicalXxx` 的類,這個類內部的方法會涉及到:`setParent`,`getParent`,如:
HierarchicalBeanFactory:有內部方法,getParent
,containsLocalBean
HierarchicalMessageSource:有內部方法,setParentMessageSource
,getParentMessageSource
rem
對於加載的命名,使用的是 `XxxLoader`,如:
ContextLoader:上下文加載(web
應用的時候)
ResourceLoader:資源加載的時候
DocumentLoader:加載 XML
文檔
僅總結上述,掌握了Spring的命名規範後(實際只在核心功能類——基礎context/beanfactory 中常見,後續其餘類命名未見強制以上規範),在閱讀源碼過程當中,就不會由於各類命名致使思緒混亂,好比:
看到ConfigurableXxx
的類,就知道它是主管設置的入口,看到getParent
,就知道對應的類應該是繼承了HierarchicalXxx
;
如:在AbstractBeanFactory
方法:getMergedBeanDefinition
中,有以下一段代碼,在進行分析的過程當中,依據命名規範,咱們能夠比較清晰地理解獲取過程
try { parentBeanName = transformedBeanName(bd.getParentName()); if (!beanName.equals(parentBeanName)) { // 遞歸獲取合併後的父定義,出口是:getParentName == null (即上述 if) pbd = getMergedBeanDefinition(parentBeanName); } else { // 這裏處理的狀況是,子 beanName 與 父 beanName 相同! // 在通常狀況下,若是咱們在同一個 xml 文件中,定義了兩個相同的 beanName,是會拋異常的, // 但這裏卻有處理 beanName 相同的狀況 // 此時就須要回顧,BeanFactory 有子類 HierarchicalBeanFactory,這種工廠具備層級關係, // 而 BeanName 能夠相同,且 beanName 分屬父子,在同一層級的 BeanFactory,即便父子關係,同名也會異常 // 因此,這裏就須要上溯父級工廠,去父級工廠就行遞歸 parentName 的 Bean定義(只有在父級工廠,才容許由相同名稱的 beanName) // 而父級工廠爲何要判斷是 ConfigurableBeanFactory 呢? // 由於 beanName 的設置入口,由 ConfigurableBeanFactory 提供,若是不是此種類型,那在 Spring 體系中,是不容許的(不規範的) BeanFactory parent = getParentBeanFactory(); if (parent instanceof ConfigurableBeanFactory) { pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName); // 從父工廠開始繼續遞歸 Bean定義 } else { throw new NoSuchBeanDefinitionException(parentBeanName, "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName + "': cannot be resolved without a ConfigurableBeanFactory parent"); } } }
再,咱們平時的使用中,經常會執行(BeanFactory)ApplicationContext
來強轉並使用BeanFactory
的方法getBean
獲取單例,就規範而言,是由於BeanFactory
是做爲獲取的入口。
常見的繼承關係有:DefaultXxx
--> 繼承 AbstractXxx
--> 繼承 ConfigurableXxx
--> Xxx
這樣,最終子類將擁有設置與獲取的方法。瞭解一些命名約束,有助於更好地理解源碼本義,以上均爲我的閱後感,若有錯誤,還請指正。