关于java:spring-50x源码学习系列四-spring-context类register方法作用

3次阅读

共计 7702 个字符,预计需要花费 20 分钟才能阅读完成。

前言

上篇博客 spring 5.0.x 源码学习系列三: AnnotationConfigApplicationContext 类的无参构造方法的作用介绍了 AnnotationConfigApplicationContext 类无参构造方法的作用, 再次回顾下次要有如下几个作用:

  1. 初始化 spring bean 工厂DefaultListableBeanFactory
  2. 通过 AnnotatedBeanDefinitionReader 将 spring6 个内置 bean 以 RootBeanDefinition 到 bean 的类型注册到工厂, 其中要记住最重要的ConfigurationClassPostProcessor
  3. 初始化ClassPathBeanDefinitionScan(这个没啥用, 真正的扫描逻辑并不是用到它)
  4. AnnotationConfigApplicationContext 的几个身份: BeanDefinitionRegistryGenericApplicationContext

接下来进入注释: AnnotationConfigApplicationContext 类 register 办法作用

一、我的项目 demo




一、AnnotationConfigApplicationContext 类 register 办法 api

  • 从上之下的源码就是它的执行过程, 附带正文
    // AnnotationConfigApplicationContext.java
    /**
     * 顾名思义,传入的是被注解的类,并且在外面做了是否存在注解的校验(能够传多个类)
     * 依据代码可知: 又是通过 AnnotatedBeanDefinitionReader 来注册的
     */
    public void register(Class<?>... annotatedClasses) {Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
        this.reader.register(annotatedClasses);
    }
    // AnnotationConfigApplicationContext.java
    /**
     * 因为上述 api 提供的是一个可变参数, 所以此处要遍历注册它
     */
    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
    /**
     * 由调用链可知,调用此办法时, 只有第一个参数有值,其余的都为 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) {

        // 记住这个创立 beanDefinition 的 api, 很罕用。// 在利用 spring 扩大点动静增加一些 beanDefinition 至 bean 工厂时很有用
        AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
        if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {return;}

        // set 进去的为 null, 因为传进来的为 null
        abd.setInstanceSupplier(instanceSupplier);
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
        abd.setScope(scopeMetadata.getScopeName());

        // 这块用的是以后类默认的 beanNameGenerator => AnnotationBeanNameGenerator
        // private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
        // 并不会应用到咱们自定义的 beanNameGenerator, 为什么?// 因为咱们压根就还没解析到 @ComponentScan 注解(这里须要有一点自定义 beanNameGenerator 的知识点)
        // 大抵能够参考我 Github 中的这个类:
        // 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));

        // 这里开始解决一些通用的注解: 比方 @Lazy、@Primary、@DependsOn、@Role、@Description
        // 获取到这些注解中的值, 并填充至传入的 AnnotatedGenericBeanDefinition
        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

        // 这块如果依照 spring 的流程来基本上用不上, 因为传入的是 null
        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, 依照失常流程来, 先疏忽它
        for (BeanDefinitionCustomizer customizer : definitionCustomizers) {customizer.customize(abd);
        }

        // 不晓得是为了啥, 要 new 这么一个对象, 可能只是为了不便传值吧 - -!BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);

        // 这块临时不晓得。。。definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

        // 注册 beanDefinition, 传入的是 registry, 有了上篇博客的根底,// 易知该 registry 就是 AnnotationConfigApplicationContext
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    }

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

        // Register bean definition under primary name.
        String beanName = definitionHolder.getBeanName();
        
        // 它后面封装了一个 definitionHolder, 当初又拆解它......
        // 该 register 是一个 AnnotationConfigApplicationContext
        // 但此时是调用父类 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");

        // 这里会校验以后的 beanDefinition, 具体校验啥没具体看,
        // 但 beanDefinition instanceof AbstractBeanDefinition 条件是成立的
        // 因为它 (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: 这个属性是 bean 工厂寄存定义的 beanDefinition
        // 因为要注册 beanDefinition, 所以先校验它是否存在, 失常流程中
        // 这里根本为 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 是否在创立, 失常的 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 注册到 bean 工厂中,// 1. 增加到 beanDefinitionMap
                // 2. 增加到 beanDefinitionNames
                // 3. 从 manualSingletonNames 中移除, 这里不分明 manualSingletonNames
                // 属性是干啥的, 不过依据名字来猜想: 寄存手动创立的单例 bean 的名字?this.beanDefinitionMap.put(beanName, beanDefinition);
                this.beanDefinitionNames.add(beanName);
                this.manualSingletonNames.remove(beanName);
            }
            this.frozenBeanDefinitionNames = null;
        }

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

二、运行后果


三、小结

  • Q1: 下面的代码执行完后(register 办法执行结束),往 bean 工厂中注册了几个 beanDefinition, bean 工厂中一共有几个 beanDefinition?
  • A1: 注册了 2 个 beanDefinition, 此时 bean 工厂中一共有 6 + 2 = 8 个 beanDefinition。

  • Q2: 当初 bean 工厂中存在的 beanDefinition 的类型总共有几种?别离是?
  • A2: 两种。别离是 RootBeanDefinitionAnnotatedGenericBeanDefinition

  • Q3: 当初有 bean 被创立进去吗?
  • A3: 没有, register 办法只是注册 beanDefinition。个别是注册一个配置类 (eg: 蕴含 @ComponentScan 注解的类) 不便 spring 的后续操作(eg: 扫描包解析注解等等)。

  • Q4: spring 认为形容 bean 的通用注解有哪些?
  • A4: @Lazy、@Primary、@DependsOn、@Role、@Description

  • spring 源码学习对应 GitHub 地址 https://github.com/AvengerEug/spring/tree/develop/resourcecode-study
  • I am a slow walker, but I never walk backwards.
正文完
 0