1. 程式人生 > >08.Spring Bean 註冊 - BeanDefinitionRegistry

08.Spring Bean 註冊 - BeanDefinitionRegistry

ace 過程 markdown itl title 描述 nco ack new

基本概念

BeanDefinitionRegistry ,該類的作用主要是向註冊表中註冊 BeanDefinition 實例,完成 註冊的過程。

它的接口定義如下:

public interface BeanDefinitionRegistry extends AliasRegistry {

    // 關鍵 -> 往註冊表中註冊一個新的 BeanDefinition 實例 
    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException;

    // 移除註冊表中已註冊的 BeanDefinition 實例
    void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    // 從註冊中取得指定的 BeanDefinition 實例
    BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    // 判斷 BeanDefinition 實例是否在註冊表中(是否註冊)
    boolean containsBeanDefinition(String beanName);

    // 取得註冊表中所有 BeanDefinition 實例的 beanName(標識)
    String[] getBeanDefinitionNames();

    // 返回註冊表中 BeanDefinition 實例的數量
    int getBeanDefinitionCount();

    // beanName(標識)是否被占用
    boolean isBeanNameInUse(String beanName);

}

再來看它的繼承關系:

技術分享圖片


2.DefaultListableBeanFactory

該類是 BeanDefinitionRegistry 接口的基本實現類,但同時也實現其他了接口的功能,這裏只探究下其關於註冊 BeanDefinition 實例的相關方法 。

首先來看它的成員變量:

// 關鍵-> 註冊表,由 BeanDefinition 的標識 (beanName) 與其實例組成
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, bean>(64);

// 標識(beanName)集合
private final List<String> beanDefinitionNames = new ArrayList<String>(64);

再來看 BeanDefinitionReaderUtils 的 registerBeanDefinition 方法。該方法的主要作用是調用註冊器(DefaultListableBeanFactory)完成註冊過程。

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
    throws BeanDefinitionStoreException {

    Assert.hasText(beanName, "Bean name must not be empty");
    Assert.notNull(beanDefinition, "BeanDefinition must not be null");

    if (beanDefinition instanceof AbstractBeanDefinition) {
        try {
            // BeanDefinition 校驗
            ((AbstractBeanDefinition) beanDefinition).validate();

        }catch (BeanDefinitionValidationException ex) {
            // 拋出異常...
        }
    }

    BeanDefinition oldBeanDefinition;

    oldBeanDefinition = this.beanDefinitionMap.get(beanName);
    if (oldBeanDefinition != null) {
        if (!isAllowBeanDefinitionOverriding()) {
            // 拋出異常...
        }else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
            // 日誌輸出...
        }
        else if (!beanDefinition.equals(oldBeanDefinition)) {
            // 日誌輸出...
        }
        else {
            // 日誌輸出...
        }
    }else {
        // 添加標識進 List
        this.beanDefinitionNames.add(beanName);
        this.manualSingletonNames.remove(beanName);
        this.frozenBeanDefinitionNames = null;
    }

    // 關鍵 -> 添加進 map
    this.beanDefinitionMap.put(beanName, beanDefinition);

    if (oldBeanDefinition != null || containsSingleton(beanName)) {
        resetBeanDefinition(beanName);
    }
}

觀察代碼可以發現該方法最重要的步驟其實就是:

this.beanDefinitionMap.put(beanName, beanDefinition);

也就是向註冊表中(beanDefinitionMap)添加 BeanDefinition 實例,完成註冊的過程。

08.Spring Bean 註冊 - BeanDefinitionRegistry