9、Spring之BeanFactory源碼分析(一)

Spring之BeanFactory源碼分析(一)

​ 注意:該隨筆內容徹底引自https://blog.csdn.net/u014634338/article/details/82865644,寫的很好,很是感謝,複製過來算是個積累,怕之後找不到。java

BeanFactory

BeanFactory提供的是最基本的IOC容器的功能,BeanFactory 只是一個接口類,並無給出容器的具體實現,固然,它有不一樣的實現類,來定義或者擴充某個功能。這篇文章的主角就是它啦。spring

啓動IOC容器

下面是一段簡單的代碼,經過編程啓動IOC 容器:編程

public void TestDefaultListableBeanFactory(){

  ClassPathResource resource  = new ClassPathResource("spring.xml");

  DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

  XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);

  reader.loadBeanDefinitions(resource);

  MyBean bean = factory.getBean(MyBean.class);

  System.out.println(bean.toString());
}

spring.xml 配置文件裏面很簡單:數據結構

<bean id="myBean" class="com.study.spring.bean.MyBean" />

這樣,咱們就能夠經過factory對象來使用DefaultListableBeanFactory 這個IOC容器了,在使用IOC容器時,須要以下步驟:
1)建立IOC配置文件的抽象資源,即配置文件編輯器

2)建立一個BeanFactory,這裏使用DefaultListableBeanFactory源碼分析

3)建立一個載入BeanDefinition的讀取器,這裏使用XmlBeanDefinitionReader 來載入XML文件形式的BeanDefinition。ui

4)從定義好的資源位置讀取配置信息,具體的解析過程由XmlBeanDefinitionReader 來完成。.net

經過一個簡短的代碼就能夠啓動spring,核心就在於DefaultListableBeanFactory,暫時就不直接跟蹤流程了,仍是來看看整個BeanFactory的設計。prototype

BeanFactory 類結構體系

BeanFactory,從名字上也很好理解,生產管理 bean 的工廠(容器),它負責生產和管理各個 bean 實例。翻譯

咱們來看下和 BeanFactory 接口相關的主要的繼承結構:

png

上面的繼承關係去除了目前不須要的類。

emmmmm,這圖看着有點頭大,慢慢來,先主要關注左邊部分,梳理一下各個BeanFactory的職能,怎麼梳理?,看源碼咯。

BeanFactory

BeanFactory 是頂級接口,定義了IOC容器最基本的形式。

public interface BeanFactory {

    //這裏能夠暫時不用管
    String FACTORY_BEAN_PREFIX = "&";

    Object getBean(String name) throws BeansException;
    ... //省略其它方法
}

定義了一些基本接口,例如 獲取bean,固然還有一些其它接口,這裏就不列出了,須要本身去了解一下。

至於 FACTORY_BEAN_PREFIX 這個其實在這裏能夠忽略,這裏仍是簡單提一下,若是不明白也無妨,與BeanFactory很類似的有一個叫FactoryBean的類,從名字上很容易混淆,BeanFactory 首先是Factoyr,而FactoryBean 是bean,只是 是一種特殊的bean, 這種特殊的bean會生產另外一種bean, 對於普通的bean,經過BeanFactory 的 getBean方法能夠獲取這個bean,而對於FactoryBean 來講,經過getBean 得到的是 FactoryBean 生產的bean,而不是FactoryBean 自己,若是想要獲取FactoryBean 自己,那麼能夠加前綴&,那麼spring 就明白,原來你是須要FactoryBean 。這個可能會在後面AOP的部分,展開來說,這裏就先說這麼多了。

ListableBeanFactory

public interface ListableBeanFactory extends BeanFactory {

    // 對於給定的名字是否含有BeanDefinition
    boolean containsBeanDefinition(String beanName);

    // 返回工廠的BeanDefinition總數
    int getBeanDefinitionCount();
    
    // 返回工廠中全部Bean的名字
    String[] getBeanDefinitionNames();

    // 返回對於指定類型 獲取bean的名字
    String[] getBeanNamesForType(ResolvableType type);
    
    //獲取包含某個註解 bean的名字
    String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);

    // 根據指定Bean名和註解類型查找指定的Bean
    <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
            throws NoSuchBeanDefinitionException;
}

HierarchicalBeanFactory

public interface HierarchicalBeanFactory extends BeanFactory {

    BeanFactory getParentBeanFactory();

    /**
     * Return whether the local bean factory contains a bean of the given name,
     * ignoring beans defined in ancestor contexts.
     * <p>This is an alternative to {@code containsBean}, ignoring a bean
     * of the given name from an ancestor bean factory.
     */
    boolean containsLocalBean(String name);

}

分層式的BeanFactory,這個工廠接口很是簡單,實現了Bean工廠的分層。相對於BeanFactory接口,它只擴展了一個重要的功能——工廠分層,能夠指定父工廠(容器),同時查找bean的時候,能夠只查找本容器,忽略父容器。

AutowireCapableBeanFactory

public interface AutowireCapableBeanFactory extends BeanFactory {

    //  這個常量代表工廠沒有自動裝配的Bean
    int AUTOWIRE_NO = 0;

    //代表根據名稱自動裝配
    int AUTOWIRE_BY_NAME = 1;

    //代表根據類型自動裝配
    int AUTOWIRE_BY_TYPE = 2;

    //代表根據構造方法裝配
    int AUTOWIRE_CONSTRUCTOR = 3;

    //被廢棄了
    @Deprecated
    int AUTOWIRE_AUTODETECT = 4;

    <T> T createBean(Class<T> beanClass) throws BeansException;

    //  給定對象,根據註釋、後處理器等,進行自動裝配
    void autowireBean(Object existingBean) throws BeansException;

    ...//省略後續方法
}

AutowireCapableBeanFactory 目前尚未深刻的研究,這個BeanFactory 增長了註解功能,能夠經過註解進行裝配(操做)的工廠(容器)。

小結

上面三個 Factory 是 BeanFactory 接口的直系親屬,三種不一樣樣式的BeanFactory ,分層容器,可列舉(查詢)容器,自動裝配容器,職能單一原則,這種接口設計,應該日常工做中常常遇到吧。

接下來在看看其它更多樣化的 BeanFactory 。

ConfigurableBeanFactory

public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {

    String SCOPE_SINGLETON = "singleton";

    String SCOPE_PROTOTYPE = "prototype";
    
    //設置父容器
    void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException;

    void setBeanClassLoader(ClassLoader beanClassLoader);

    ClassLoader getBeanClassLoader();

    void setBeanExpressionResolver(@Nullable BeanExpressionResolver resolver);

    BeanExpressionResolver getBeanExpressionResolver();

    /*
     * 設置 轉換服務
     */
    void setConversionService(ConversionService conversionService);

    ConversionService getConversionService();

    void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar);

    /*
     * 註冊屬性編輯器
     */
    void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass);

    void copyRegisteredEditorsTo(PropertyEditorRegistry registry);

    void setTypeConverter(TypeConverter typeConverter);

    TypeConverter getTypeConverter();

    //設置一個Bean後處理器
    void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);

    int getBeanPostProcessorCount();

    void registerScope(String scopeName, Scope scope);

    String[] getRegisteredScopeNames();

    Scope getRegisteredScope(String scopeName);

    void copyConfigurationFrom(ConfigurableBeanFactory otherFactory);
    /*
     * 給指定的Bean註冊別名
     */
    void registerAlias(String beanName, String alias) throws BeanDefinitionStoreException;

    BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    //判斷指定Bean是否爲一個工廠Bean
    boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException;

    void setCurrentlyInCreation(String beanName, boolean inCreation);

    boolean isCurrentlyInCreation(String beanName);

    void registerDependentBean(String beanName, String dependentBeanName);

    String[] getDependentBeans(String beanName);

    String[] getDependenciesForBean(String beanName);

    void destroyBean(String beanName, Object beanInstance);

    void destroyScopedBean(String beanName);

    void destroySingletons();
    
    ...//省略部分方法

}

ConfigurableBeanFactory 繼承了 HierarchicalBeanFactory,SingletonBeanRegistry

先看一下接口SingletonBeanRegistry的源碼:

SingletonBeanRegistry

public interface SingletonBeanRegistry {

    //註冊一個單例類  
    void registerSingleton(String beanName, Object singletonObject);


    Object getSingleton(String beanName);


    boolean containsSingleton(String beanName);


    String[] getSingletonNames();

    int getSingletonCount();

    //不清楚
    Object getSingletonMutex();

}

能夠看到,SingletonBeanRegistry這個接口很是簡單,實現了單例類註冊的功能。

ConfigurableBeanFactory同時繼承了HierarchicalBeanFactory 和 SingletonBeanRegistry 這兩個接口,即同時繼承了分層和單例類註冊的功能。

ConfigurableBeanFactory 正如其名字同樣,能夠配置的BeanFactory,裏面有不少接口方法,我也沒有去細研究每個方法,後面用到了,再來具體分析就能夠了,瞭解瞭解,知道大概用處就能夠了。

ConfigurableListableBeanFactory

public interface ConfigurableListableBeanFactory
        extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {

    //忽略自動裝配的依賴類型
    void ignoreDependencyType(Class<?> type);
    
    //忽略自動裝配的接口
    void ignoreDependencyInterface(Class<?> ifc);

    //返回註冊的Bean定義
    BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;


    Iterator<String> getBeanNamesIterator();

    ...//忽略部分方法
}

工廠接口ConfigurableListableBeanFactory同時繼承了3個接口,ListableBeanFactory、AutowireCapableBeanFactory 和 ConfigurableBeanFactory,能夠說功能以及很全面了。

對於BeanFactory 體系中左邊部分,大體差很少了,如今看看右半邊狀況

BeanDefinitionRegistry

顧名思義,這個是註冊 BeanDefinition的

public interface BeanDefinitionRegistry extends AliasRegistry {

    //給定bean名稱,註冊一個新的bean定義
    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException;

    //根據指定Bean名移除對應的Bean定義
    void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    根據指定bean名獲得對應的Bean定義
    BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    查找,指定的Bean名是否包含Bean定義
    boolean containsBeanDefinition(String beanName);

    //返回本容器內全部註冊的Bean定義名稱
    String[] getBeanDefinitionNames();

    //指定Bean名是否被註冊過。
    int getBeanDefinitionCount();

   //指定Bean名是否被註冊過。
    boolean isBeanNameInUse(String beanName);

}

這個接口很簡單,就是對BeanDefinition的操做,然而咱們尚未了解BeanDefinition 的結構,可是並不影響咱們分析,由於從名字就知道這個指代的是一個bean的定義,也就是將xml中的bean 翻譯成了具體的數據結構。

如今回過頭來,咱們再看看DefaultListableBeanFactory類圖

png

對於左邊部分,則是各類功能的BeanFactory,右邊部分則是對BeanDefinition的功能操做,中間部分則是單例Bean功能服務,中間部分咱們沒有分析源代碼,可是經過名字咱們已經很好的知道了它的功能,而FactoryBeanRegistrySupport 則表示了對 FactoryBean的支持,(FactoryBean在前面BeanFactory簡單提了一下喲)

如今對每一個BeanFactory的職能內心大概有譜了,這樣在後面的時候,才知道這個功能屬於哪一個模塊,而不至於腦殼一團漿糊。

對於DefaultListableBeanFactory 咱們並無取分析它,由於DefaultListableBeanFactory 中實現了上面接口中的全部方法,涉及了不少細節,從代碼角度來看的話,那真的是很難一下分析透,可是若是從功能模塊上來看的話,咱們也知道了它大概能夠幹什麼,能夠說是一個比較成熟的容器了,既然如今咱們知道了裝bean的容器了,那麼bean又從何處來呢,固然是xml,可是xml又如何轉換成數據結構的呢,這個就須要回到咱們最開的代碼了:

public void TestDefaultListableBeanFactory(){

  ClassPathResource resource  = new ClassPathResource("spring.xml"); //3

  DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); //5

  XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);//7

  reader.loadBeanDefinitions(resour ce);//9

  MyBean bean = factory.getBean(MyBean.class); //11

  System.out.println(bean.toString());

}

如今第5,11行代碼咱們已經大體清楚了,主要的還剩3,4,9行代碼了,這個就先留到後面再來吧。

BeanDefinition

Bean的定義主要由BeanDefinition來描述的,做爲Spring中用於包裝Bean的數據結構,先來看看BeanDefinition一個繼承結構吧(非完整繼承結構)

png

一個BeanDefinition描述了一個bean的實例,包括屬性值,構造方法參數值和繼承自它的類的更多信息。

BeanDefinition 源碼淺析

//標準單例做用域 標識符:「singleton」。
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;

//標準原型做用域的範圍標識符:「prototype」。
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

//表示BeanDefinition是應用程序主要部分的角色提示。 一般對應於用戶定義的bean。
int ROLE_APPLICATION = 0;

//表示BeanDefinition是某些大型配置的支持部分的角色提示,一般是一個外部ComponentDefinition。
//當查看某個特定的ComponentDefinition時,認爲bean很是重要,
//以便在查看應用程序的總體配置時可以意識到這一點。

int ROLE_SUPPORT = 1;

//角色提示代表一個BeanDefinition是提供一個徹底背景的角色,而且與最終用戶沒有關係。

ROLE_SUPPORT =1實際上就是說,我這個Bean是用戶的,是從配置文件中過來的。

ROLE_INFRASTRUCTURE = 2 就是說 這Bean是Spring本身的,

上面是BeanDifinition的一些基本屬性信息,一個就是標識下當前Bean的做用域,另外就是標識一下這個Bean是內部的仍是外部的。下面來看這個接口爲其子類都提供了哪些具體的行爲方法:
1.當前Bean的className get&set方法

//指定此bean定義的bean類名稱。
//類名稱能夠在bean factory後期處理中修改,一般用它的解析變體替換原來的類名稱。
void setBeanClassName(String beanClassName);

//返回此bean定義的當前bean類名稱。
//須要注意的是,這不必定是在運行時使用的實際類名,以防子類定義覆蓋/繼承其父類的類名。
//此外,這可能只是調用工廠方法的類,或者它 在調用方法的工廠bean引用的狀況下甚至多是空的。
//所以,不要認爲這是在運行時定義的bean類型,而只是將其用於在單獨的bean定義級別進行解析。
String getBeanClassName();

2.Bean的做用域get&set方法

//覆蓋此bean的目標範圍,指定一個新的範圍名稱。
void setScope(String scope);
//返回此bean的當前目標做用域的名稱,若是沒有肯定,返回null
String getScope();

3.懶加載的get&set方法

//設置這個bean是否應該被延遲初始化。若是{false},那麼這個bean將在啓動時由bean工廠實例化,
//這些工廠執行單例的當即初始化。
//懶加載 <bean lazy-init="true/false">
void setLazyInit(boolean lazyInit);
//返回這個bean是否應該被延遲初始化,即不是在啓動時當即實例化。只適用於單例bean。
boolean isLazyInit();

4.依賴關係設置

//設置這個bean依賴被初始化的bean的名字。 bean工廠將保證這些bean首先被初始化。
//<bean depends-on="">
void setDependsOn(String... dependsOn);
//返回這個bean依賴的bean名稱。
String[] getDependsOn();

5.是不是自動轉配設置

//設置這個bean是不是得到自動裝配到其餘bean的候選人。
//須要注意是,此標誌旨在僅影響基於類型的自動裝配。
//它不會影響按名稱的顯式引用,即便指定的bean沒有標記爲autowire候選,也能夠解決這個問題。
//所以,若是名稱匹配,經過名稱的自動裝配將注入一個bean。
void setAutowireCandidate(boolean autowireCandidate);

//返回這個bean是不是自動裝配到其餘bean的候選者。就是是否在其餘類中使用autowired來注入當前Bean的
//是否爲被自動裝配 <bean autowire-candidate="true/false">
boolean isAutowireCandidate();

並無徹底列舉 BeanDifinition 中的方法或者屬性,大體明白 Bean的定義主要由BeanDefinition來描述的,做爲Spring中用於包裝Bean的數據結構就能夠了,關於BeanDifinition 的更多接口實現,這個根據本身狀況去看看就能夠了。

小結

瞭解了BeanFactory的大體結構後,來看看下面一段簡單代碼,相信理解就更加深入了:

public void TestDefaultListableBeanFactory(){

  DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

  AbstractBeanDefinition beanDefinition = new RootBeanDefinition(MyBean.class);

  factory.registerBeanDefinition("myBean",beanDefinition);

  //能夠經過構造方法注入依賴,固然咱們這裏沒有
  //beanDefinition.setConstructorArgumentValues();

  //能夠經過 setter 方法注入依賴,固然咱們這裏也沒有
  //beanDefinition.setPropertyValues();

  MyBean bean = factory.getBean(MyBean.class);

  System.out.println(bean.toString());

}

在前面咱們用的ClassPathResource,XmlBeanDefinitionReader 從文件中讀取的bean配置信息,如今咱們知道了BeanDifinition 以及BeanDefinitionRegistry,那麼其實咱們能夠手動註冊BeanDifinition ,這樣我在最開始的代碼基礎上,又再次細分了功能了,層次也更加的清楚了。

總結

咱們從 DefaultListableBeanFactory 出發,大體瞭解了一下 BeanFactory的體系結構,BeanFactory有三個直系親屬:

ListableBeanFactory(可列舉的容器(多花樣查詢)),HierarchicalBeanFactory(分層次容器,可有父容器),AutowireCapableBeanFactory(自動裝配容器),這三個容器定義了BeanFactory的基本面貌,在這個三個直系親屬下面又派生了兩個複雜的容器:ConfigurableBeanFactory,ConfigurableListableBeanFactory,可配置的(可操做)的容器,經過這兩個BeanFactory 可有修改容器中的bean,功能又更加高級了,集成了單例bean 服務,以及BeanDefinition 註冊服務,那麼對於 DefaultListableBeanFactory 來講,此時它就是一個可註冊,可配置,可獲取的BeanFactory ,就容器方面而言功能已經健全了。

相關文章
相關標籤/搜索