spring 5.0.x源碼學(xué)習(xí)系列四: AnnotationConfigApplicationContext類register方法作用

前言

上篇博客spring 5.0.x源碼學(xué)習(xí)系列三: AnnotationConfigApplicationContext類的無(wú)參構(gòu)造方法的作用介紹了AnnotationConfigApplicationContext類無(wú)參構(gòu)造方法的作用, 再次回顧下主要有如下幾個(gè)作用:

  1. 初始化spring bean工廠DefaultListableBeanFactory
  2. 通過(guò)AnnotatedBeanDefinitionReader將spring6個(gè)內(nèi)置bean以RootBeanDefinition到bean的類型注冊(cè)到工廠, 其中要記住最重要的ConfigurationClassPostProcessor
  3. 初始化ClassPathBeanDefinitionScan(這個(gè)沒(méi)啥用, 真正的掃描邏輯并不是用到它)
  4. AnnotationConfigApplicationContext的幾個(gè)身份: BeanDefinitionRegistryGenericApplicationContext

接下來(lái)進(jìn)入正文: AnnotationConfigApplicationContext類register方法作用

一、項(xiàng)目demo

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

一、AnnotationConfigApplicationContext類register方法api

  • 從上之下的源碼就是它的執(zhí)行過(guò)程, 附帶注釋
    // AnnotationConfigApplicationContext.java
    /**
     * 顧名思義,傳入的是被注解的類,并且在里面做了是否存在注解的校驗(yàn)(可以傳多個(gè)類)
     * 根據(jù)代碼可知: 又是通過(guò)AnnotatedBeanDefinitionReader來(lái)注冊(cè)的
     */
    public void register(Class<?>... annotatedClasses) {
        Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
        this.reader.register(annotatedClasses);
    }
    // AnnotationConfigApplicationContext.java
    /**
     * 因?yàn)樯鲜鯽pi提供的是一個(gè)可變參數(shù), 所以此處要遍歷注冊(cè)它
     */
    public void register(Class<?>... annotatedClasses) {
        for (Class<?> annotatedClass : annotatedClasses) {
            registerBean(annotatedClass);
        }
    }
    // AnnotationConfigApplicationContext.java
    /**
     * 將代碼邏輯委托給另外方法
     */
    public void registerBean(Class<?> annotatedClass) {
        doRegisterBean(annotatedClass, null, null, null);
    }
    // AnnotationConfigApplicationContext.java
    /**
     * 由調(diào)用鏈可知,調(diào)用此方法時(shí), 只有第一個(gè)參數(shù)有值,其他的都為null
     * @param annotatedClass
     * @param instanceSupplier
     * @param name
     * @param qualifiers
     * @param definitionCustomizers
     * @param <T>
     */
    <T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
            @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

        // 記住這個(gè)創(chuàng)建beanDefinition的api, 很常用。
        // 在利用spring擴(kuò)展點(diǎn)動(dòng)態(tài)添加一些beanDefinition至bean工廠時(shí)很有用
        AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
        if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
            return;
        }

        // set進(jìn)去的為null, 因?yàn)閭鬟M(jìn)來(lái)的為null
        abd.setInstanceSupplier(instanceSupplier);
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
        abd.setScope(scopeMetadata.getScopeName());

        // 這塊用的是當(dāng)前類默認(rèn)的beanNameGenerator => AnnotationBeanNameGenerator
        // private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
        // 并不會(huì)使用到我們自定義的beanNameGenerator, 為什么?
        // 因?yàn)槲覀儔焊瓦€沒(méi)解析到@ComponentScan注解(這里需要有一點(diǎn)自定義beanNameGenerator的知識(shí)點(diǎn))
        // 大致可以參考我Github中的這個(gè)類:
        // https://github.com/AvengerEug/spring/blob/develop/ioc/src/main/java/com/eugene/sumarry/ioc/annotationtype/MyBeanNameGenerator.java
        String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

        // 這里開(kāi)始處理一些通用的注解: 比如@Lazy、@Primary、@DependsOn、@Role、@Description
        // 獲取到這些注解中的值, 并填充至傳入的AnnotatedGenericBeanDefinition
        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

        // 這塊如果按照spring的流程來(lái)基本上用不上, 因?yàn)閭魅氲氖莕ull
        if (qualifiers != null) {
            for (Class<? extends Annotation> qualifier : qualifiers) {
                if (Primary.class == qualifier) {
                    abd.setPrimary(true);
                }
                else if (Lazy.class == qualifier) {
                    abd.setLazyInit(true);
                }
                else {
                    abd.addQualifier(new AutowireCandidateQualifier(qualifier));
                }
            }
        }

        // 傳入的也為null, 按照正常流程來(lái), 先忽略它
        for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
            customizer.customize(abd);
        }

        // 不知道是為了啥, 要new這么一個(gè)對(duì)象, 可能只是為了方便傳值吧 - -!
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);

        // 這塊暫時(shí)不知道。。。
        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

        // 注冊(cè)beanDefinition, 傳入的是registry, 有了上篇博客的基礎(chǔ),
        // 易知該registry就是AnnotationConfigApplicationContext
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    }

    // BeanDefinitionReaderUtils.java
    /**
     * 注冊(cè)beanDefinition
     */
    public static void registerBeanDefinition(
            BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
            throws BeanDefinitionStoreException {

        // Register bean definition under primary name.
        String beanName = definitionHolder.getBeanName();
        
        // 它前面封裝了一個(gè)definitionHolder, 現(xiàn)在又拆解它......
        // 該register是一個(gè)AnnotationConfigApplicationContext
        // 但此時(shí)是調(diào)用父類GenericApplicationContext的registerBeanDefinition方法
        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

        // Register aliases for bean name, if any.
        String[] aliases = definitionHolder.getAliases();
        if (aliases != null) {
            for (String alias : aliases) {
                registry.registerAlias(beanName, alias);
            }
        }
    }

    // DefaultListableBeanFactory.java
    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");

        // 這里會(huì)校驗(yàn)當(dāng)前的beanDefinition, 具體校驗(yàn)啥沒(méi)具體看,
        // 但beanDefinition instanceof AbstractBeanDefinition條件是成立的
        // 因?yàn)樗?AnnotatedGenericBeanDefinition)繼承了AbstractBeanDefinition
        if (beanDefinition instanceof AbstractBeanDefinition) {
            try {
                ((AbstractBeanDefinition) beanDefinition).validate();
            }
            catch (BeanDefinitionValidationException ex) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                        "Validation of bean definition failed", ex);
            }
        }

        // beanDefinitionMap: 這個(gè)屬性是bean工廠存放定義的beanDefinition
        // 因?yàn)橐?cè)beanDefinition, 所以先校驗(yàn)它是否存在, 正常流程中
        // 這里基本為null
        BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
        if (existingDefinition != null) {
            if (!isAllowBeanDefinitionOverriding()) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                        "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
                        "': There is already [" + existingDefinition + "] bound.");
            }
            else if (existingDefinition.getRole() < beanDefinition.getRole()) {
                // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
                if (logger.isWarnEnabled()) {
                    logger.warn("Overriding user-defined bean definition for bean '" + beanName +
                            "' with a framework-generated bean definition: replacing [" +
                            existingDefinition + "] with [" + beanDefinition + "]");
                }
            }
            else if (!beanDefinition.equals(existingDefinition)) {
                if (logger.isInfoEnabled()) {
                    logger.info("Overriding bean definition for bean '" + beanName +
                            "' with a different definition: replacing [" + existingDefinition +
                            "] with [" + beanDefinition + "]");
                }
            }
            else {
                if (logger.isDebugEnabled()) {
                    logger.debug("Overriding bean definition for bean '" + beanName +
                            "' with an equivalent definition: replacing [" + existingDefinition +
                            "] with [" + beanDefinition + "]");
                }
            }
            this.beanDefinitionMap.put(beanName, beanDefinition);
        }
        else {
            // 判斷bean是否在創(chuàng)建, 正常的register流程中, 返回的基本為false
            if (hasBeanCreationStarted()) {
                // Cannot modify startup-time collection elements anymore (for stable iteration)
                synchronized (this.beanDefinitionMap) {
                    this.beanDefinitionMap.put(beanName, beanDefinition);
                    List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                    updatedDefinitions.addAll(this.beanDefinitionNames);
                    updatedDefinitions.add(beanName);
                    this.beanDefinitionNames = updatedDefinitions;
                    if (this.manualSingletonNames.contains(beanName)) {
                        Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
                        updatedSingletons.remove(beanName);
                        this.manualSingletonNames = updatedSingletons;
                    }
                }
            }
            else {
                // 將beanD注冊(cè)到bean工廠中,
                // 1. 添加到beanDefinitionMap
                // 2. 添加到beanDefinitionNames
                // 3. 從manualSingletonNames中移除, 這里不清楚manualSingletonNames
                // 屬性是干啥的, 不過(guò)根據(jù)名字來(lái)猜測(cè): 存放手動(dòng)創(chuàng)建的單例bean的名字?
                this.beanDefinitionMap.put(beanName, beanDefinition);
                this.beanDefinitionNames.add(beanName);
                this.manualSingletonNames.remove(beanName);
            }
            this.frozenBeanDefinitionNames = null;
        }

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

二、運(yùn)行結(jié)果

在這里插入圖片描述

在這里插入圖片描述

三、小結(jié)

  • Q1: 上面的代碼執(zhí)行完后(register方法執(zhí)行完畢),往bean工廠中注冊(cè)了幾個(gè)beanDefinition, bean工廠中一共有幾個(gè)beanDefinition?
  • A1: 注冊(cè)了2個(gè)beanDefinition, 此時(shí)bean工廠中一共有 6 + 2 = 8 個(gè)beanDefinition。

  • Q2: 現(xiàn)在bean工廠中存在的beanDefinition的類型總共有幾種?分別是?
  • A2: 兩種。 分別是RootBeanDefinitionAnnotatedGenericBeanDefinition 。

  • Q3: 現(xiàn)在有bean被創(chuàng)建出來(lái)嗎?
  • A3: 沒(méi)有, register方法只是注冊(cè)beanDefinition。 一般是注冊(cè)一個(gè)配置類(eg: 包含@ComponentScan注解的類)方便spring的后續(xù)操作(eg: 掃描包解析注解等等)。

  • Q4: spring認(rèn)為描述bean的通用注解有哪些?
  • A4: @Lazy、@Primary、@DependsOn、@Role、@Description

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容