Spring AOP IOC 以外 —— 類的命名

規範命名,有助於思想的傳承。

最近在閱讀Spring的過程當中,發現除了 AOP,IOC以外,還有許多被忽略的有助於閱讀/理解源碼的點,在此一一作筆記,供人蔘閱,但願有所幫助。若有錯漏,但願可以指出以便修正,不勝感激。web

Spring 的源碼中,核心類的命名與功能劃分具備必定的規範,瞭解後,在閱讀Spring源碼中,有些許的幫助。spa

冪等與非冪等/讀寫分離

Spring底層核心類,不少接口是按照冪等與非冪等/讀寫分離進行劃分的:
BeanFactory:內部方法均爲獲取或者判斷的方法,如:getBean,containsBean等;
ConfigurableBeanFactory:繼承了BeanFactory後,內部定義了屬性設置的入口,非冪等的,如:setParentBeanFactorysetConversionService
Environment:內部方法均爲獲取,或者判斷的方法,如:containsPropertygetActiveProfiles
ConfigurableEnvironment:繼承了Environment後,內部方法定義的是設置方法,非冪等的,如:setActiveProfilesmergecode

命名習慣01
Spring 的 接口定義中,接口的命名有其規範性存在,
單純的冪等性方法,直接按實際做用命名(主要爲冪等性),
非冪等性,則在實際做用命名前(繼承了冪等性類),增長 `Configurable`,
基礎實現,則在非冪等性的基礎上(繼承了非冪等性類),對方法進行通用的基礎實現

Environment:擁有獲取 propertyprofile 的方法
ConfigurableEnvironment:擁有setActiveProfiles 等方法
AbstractEnvironment:對以上兩個類方法進行基礎實現orm


ApplicationContext:擁有獲取 IDBeanFactory 等方法,如:getApplicationNamegetParentgetAutowireCapableBeanFactory
ConfigurableApplicationContext:擁有設置對應屬性的方法,如:setEnvironmentsetParent
AbstractApplicationContext:對上述兩個類方法進行基礎實現xml


PropertyResolver:獲取屬性的方法,如:getPropertycontainsProperty
ConfigurablePropertyResolver:設置性的方法,如:setConversionServicesetPlaceholderPrefix
AbstractPropertyResolver:對以上兩個類方法繼續基礎實現繼承


PropertyAccessor:屬性的判斷及獲取
ConfigurablePropertyAccessor:屬性的設置
AbstractPropertyAccessor:基本實現遞歸


命名習慣02
針對向某個 Collection 中添加/註冊某個實例,Spring 經常使用的命名方式是使用 Registry 做爲後綴,就實際功能而言,這些類是將對應實例歸入Spring容器管理的入口!

ConverterRegistry:轉換器註冊器,提供了 addConverteraddConverterFactory等方法
AliasRegistry:別名註冊器,registerAliasremoveAliasisAliasgetAliases
BeanDefinitionRegistry:Bean定義註冊器,提供了registerBeanDefinitionremoveBeanDefinition
SingletonBeanRegistry:單例註冊器,方法:registerSingletoncontainsSingleton接口

命名習慣03
默認實現,在Abstract***以後,使用了Default前綴

如:DefaultConversionServiceDefaultListableBeanFactoryDefaultNamespaceHandlerResolver資源

命名習慣04
當一個類有層級概念(代表該類在處理時須要考慮父級狀況)時,會定義一個前綴:`HierarchicalXxx` 的類,這個類內部的方法會涉及到:`setParent`,`getParent`,如:

HierarchicalBeanFactory:有內部方法,getParentcontainsLocalBean
HierarchicalMessageSource:有內部方法,setParentMessageSourcegetParentMessageSourcerem

命名習慣05
對於加載的命名,使用的是 `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這樣,最終子類將擁有設置與獲取的方法。瞭解一些命名約束,有助於更好地理解源碼本義,以上均爲我的閱後感,若有錯誤,還請指正。

相關文章
相關標籤/搜索