spring源碼閱讀2-1——bean的管理

本文開始,將利用《spring源碼閱讀1——環(huán)境搭建&閱讀方法》中提到的方法逐步對spring源碼進行解讀。

本文主要對DefaultListtableBeanFactory的父級接口進行剖析、解讀,旨在探究明白spring是如何
對組件(bean)進行管理的。
本文使用的spring版本:4.1.1.RELEASE

順藤摸瓜——DefaultListableBeanFactory

public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        HelloService helloService = context.getBean(HelloService.class);
        System.out.println(helloService.sayHello());
    }

還是從這個main函數(shù)入手,容器的getBean(Class<T> requiredType)方法,是通過類對象來獲取實例對象,通過調試可以知道,該方法的具體實現(xiàn)在

AbstractApplicationContext.java

    @Override
    public <T> T getBean(Class<T> requiredType) throws BeansException {
        assertBeanFactoryActive();
        return getBeanFactory().getBean(requiredType);
    }

查看getBeanFactory()方法

AbstractRefreshableApplicationContext.java

    /** Bean factory for this context */
    private DefaultListableBeanFactory beanFactory;

        ...

    @Override
    public final ConfigurableListableBeanFactory getBeanFactory() {
        synchronized (this.beanFactoryMonitor) {
            if (this.beanFactory == null) {
                throw new IllegalStateException("BeanFactory not initialized or already closed - " +
                        "call 'refresh' before accessing beans via the ApplicationContext");
            }
            return this.beanFactory;
        }
    }

通過debug過程中,可以看到這個beanFactory的類型是DefaultListableBeanFactory。

beanFactory

繼續(xù)調試,進入getBean方法,可以看到這個方法的具體實現(xiàn)確實在類DefaultListableBeanFactory中

    @Override
    public <T> T getBean(Class<T> requiredType) throws BeansException {
        return getBean(requiredType, (Object[]) null);
    }

    @Override
    public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
        Assert.notNull(requiredType, "Required type must not be null");
        String[] beanNames = getBeanNamesForType(requiredType);
        if (beanNames.length > 1) {
            ArrayList<String> autowireCandidates = new ArrayList<String>();
            for (String beanName : beanNames) {
                if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
                    autowireCandidates.add(beanName);
                }
            }
            if (autowireCandidates.size() > 0) {
                beanNames = autowireCandidates.toArray(new String[autowireCandidates.size()]);
            }
        }
        ...
    }

至此,我感覺已經找到了所謂的“瓜”,就是DefaultListableBeanFactory這個類,暫且不糾結這個beanFactory是如何實例化的,這不是本文的重點。


化整為零

這一節(jié),我們將整理出DefaultListableBeanFactory這個類的層次結構,逐步了解各個關聯(lián)的類的作用。

子類

通過工具,查看DefaultListableBeanFactory有哪些子類

DefaultListableBeanFactory的子類

可以看到DefaultListableBeanFactory只有一個子類XmlBeanFactory。回顧spring中bean的幾種裝配方式,在對照該類的注釋,可知這個類就是使用xml文件來裝配bean組件的。后面的章節(jié)會詳細介紹這個類,這里不做贅述。

父級層次結構

同樣的,用工具查看DefaultListableBeanFactory的層級結構以及類圖

小技巧:
Ctrl + H 展示當前類的層級結構圖:左上角可選父類、子類以及全部展示視圖
Ctrl + Alt + Shift + U 展示當前類的類圖,可過濾展示內容
DefaultListableBeanFactory的父類
類圖

通過這個圖可以知道DefaultListableBeanFactory繼承了AbstractAutowireCapableBeanFactory類,并且實現(xiàn)了ConfigurableListableBeanFactory接口和BeanDefinitionRegistry接口,已經可以清晰地從全局角度了解DefaultListableBeanFactory的脈絡。


各個擊破——接口

小技巧:
Ctrl + F12 查看當前類的所有方法和屬性
AliasRegistry
alias注冊管理

在對bean進行定義時,除了使用id屬性來指定名稱之外,為了提供多個名稱,可以使用alias標簽來指定。該接口定義了對alias的注冊管理功能。

getAliases()  :  獲取alias標簽數(shù)組
isAlias()  :  判斷標簽是否存在
registerAlias()  :  注冊alias標簽
removeAlias()  :  移除已注冊的alias標簽
BeanDefinitionRegistry
bean配置清單管理

提供bean的配置清單注冊管理功能。

方法說明:
registerBeanDefinition()  :  注冊BeanDefinition
removeBeanDefinition()  :  移除BeanDefinition
isBeanNameInUse()  :  重名校驗
containsBeanDefinition()  :  工廠中是否存在BeanDefinition
getBeanDefinitionCount()  :  返回工廠中BeanDefinition的總數(shù)
getBeanDefinitionNames()  :  返回工廠中BeanDefinition的名稱


bean的配置清單(BeanDefinition)是什么?
回憶下spring中,根據(jù)xml文檔來裝配bean,舉個栗子:
<bean id="123" class="com.spring.student">   
    <property name="name" value="XiaoMing" />   
    <property name="age" value="17" />
    <property name="sex" value="man" />
</bean>  
這是一個student實例的配置文件,里面記錄著id為123的student實例的姓名、年齡和
性別三個屬性,spring讀取以后就保存為BeanDefinition,容器可以根據(jù)這個信息進行
實例化。這就是配置清單~
BeanFactory

查看BeanFactory接口中定義的方法:

基本的bean管理工廠

BeanFactory接口,定義了一個基本的bean管理工廠。

方法說明:
containsBean()  :  工廠中是否存在bean實例
getAliases()  :  獲取實例bean的別名數(shù)組
getBean()  :  獲取bean實例(多個重載方法)
getType()  ;  獲取bean實例類型
isPrototype()  :  bean實例是否為prototype
isSingleton()  :  bean實例是否為單例
isTypeMatch()  :  bean實例類型是否和給定值匹配
ListableBeanFactory
bean配置清單的管理

這個接口是對BeanFactory的擴展,提供了根據(jù)條件獲取bean的配置清單(BeanDefinition,暫且就這么稱呼吧)。

方法說明:
containsBeanDefinition()  :  工廠中是否存在BeanDefinition
getBeanDefinitionCount()  :  返回工廠中BeanDefinition的總數(shù)
getBeanDefinitionNames()  :  返回工廠中BeanDefinition的名稱
getBeanNamesForType()  :  根據(jù)類型獲取BeanDefinition的名稱
getBeansOfType()  :  根據(jù)類型獲取Bean
getBeanNamesForAnnotation()  :  根據(jù)注解獲取Bean名稱
getBeansWithAnnotation()  :  根據(jù)注解獲取Bean
findAnnotationOnBean()  :  獲取BeanDefinition的注解

HierarchicalBeanFactory
分層的BeanFactory

同樣是繼承于BeanFactory,這個接口主要和層級關系相關,包含兩個方法:

方法說明:
getParentBeanFactory()  :  獲取父級BeanFactory
containsLocalBean()  :  返回當前BeanFactory是否存在bean

如果對方法的作用有所疑問,也沒有關系,到后面碰到對其實現(xiàn)和使用,便會豁然開朗。
AutowireCapableBeanFactory
依賴注入BeanFactory

這個接口為BeanFactory定義了支持依賴注入功能,主要包含:

方法說明:
createBean()  :  創(chuàng)建bean實例
autowireBean()  :  注入bean實例
configureBean()  :  配置bean實例,注入bean屬性,執(zhí)行回調函數(shù)等
resolveDependency()  :  解決bean實例的依賴
autowireBeanProperties()  :  注入bean實例的屬性
applyBeanPropertyValues()  :  注入bean實例的屬性值
initializeBean()  :  初始化bean實例
applyBeanPostProcessorsBeforeInitialization()  :  應用bean的前置處理
applyBeanPostProcessorsAfterInitialization()  :  應用bean的后置處理
destroyBean()  :  銷毀bean實例
SigletonBeanRegistry
單例SingletonBean注冊管理

這個接口定義了容器對單例的注冊管理方法。

方法說明:
registerSingleton()  :  注冊bean
getSingleton()  :  獲取bean
containsSingleton()  :  返回是否包含bean
getSingletonNames()  :  獲取bean實例(單例)的名稱數(shù)組
getSingletonCount()  :  獲取容器中bean實例的總數(shù)
ConfigurableBeanFactory
bean工廠的配置

這個接口繼承了SingletonBeanRegistry和HierarchicalBeanFactory兩個接口,增加了beanFactory的配置功能。主要是許多屬性的get和set方法。由于配置項較多,較為復雜,這里先不詳細介紹

ConfigurableListableBeanFactory
bean工廠的配置

新增了忽略類型以及接口

總結

至此,已經了解完所有的相關接口,整理下所有的接口中定義的概念:

  • Bean : 組件對象,sping容器所管理的對象
  • SingletonBean : 特殊的bean,其在容器中僅有一個實例
  • BeanDefinition : bean的配置清單,或者說定義文件,spring可以根據(jù)該文件實例化出對象
  • Alias : bean的別名,一個bean可以有多個名稱
  • BeanFactory : bean工廠,為其他組件提供管理容器
BeanFactory的整體框架

通過這個類圖,感覺整個BeanFactory生態(tài)圈已經構建起來了。不得不感嘆面向對象的魅力,僅僅是定義了接口,便展示了一個完整的功能模塊。

本文到這就要結束了,回顧下
    1、首先是通過調試的方法,找到了整個bean管理功能模塊的核心DefaultListableBeanFactory
    2、然后是對DefaultListableBeanFactory所實現(xiàn)的各個父級接口進行源碼閱讀和分析
    3、最后再通過系統(tǒng)的整理出該功能模塊的概覽
    通過以上三步,完成了BeanFactory的整個功能定義的概覽,下次會給大家?guī)淼氖侨绾我徊揭徊降?實現(xiàn)上述的定義

本文到此就結束,希望能夠幫到大家。
純屬原創(chuàng),轉載請聲明出處。
                                                    ——作者:陳來件(QQ:810522442)
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容