spring 5.0.x源码学习系列四: spring context类register方法作用

前言

上篇博客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

spring 5.0.x源码学习系列四: spring context类register方法作用_第1张图片
spring 5.0.x源码学习系列四: spring context类register方法作用_第2张图片
spring 5.0.x源码学习系列四: spring context类register方法作用_第3张图片
spring 5.0.x源码学习系列四: spring context类register方法作用_第4张图片

一、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 
     */
     void doRegisterBean(Class annotatedClass, @Nullable Supplier instanceSupplier, @Nullable String name,
            @Nullable Class[] 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 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 updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                    updatedDefinitions.addAll(this.beanDefinitionNames);
                    updatedDefinitions.add(beanName);
                    this.beanDefinitionNames = updatedDefinitions;
                    if (this.manualSingletonNames.contains(beanName)) {
                        Set 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);
        }
    }

二、运行结果

spring 5.0.x源码学习系列四: spring context类register方法作用_第5张图片
spring 5.0.x源码学习系列四: spring context类register方法作用_第6张图片

三、小结

  • 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

你可能感兴趣的:(javaspring)