美文网首页
spring 5.0.x源码学习系列四: AnnotationC

spring 5.0.x源码学习系列四: AnnotationC

作者: avengerEug | 来源:发表于2021-03-18 09:14 被阅读0次

    前言

    上篇博客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 5.0.x源码学习系列四: AnnotationC

          本文链接:https://www.haomeiwen.com/subject/luhucltx.html