zoukankan      html  css  js  c++  java
  • spring IOC

    接着上一篇. 这里来看一下 register(componentClasses)

    register

    @Override
    public void register(Class<?>... componentClasses) {
        Assert.notEmpty(componentClasses, "At least one component class must be specified");
        this.reader.register(componentClasses);
    }

    从代码来看, 注册的工作, 是 AnnotatedBeanDefinitionReader 来完成的. 由于 componentClasses 是一个可变数组, 所以, 还是需要对他进行循环注册的.

    循环里面, 最终会调用 org.springframework.context.annotation.AnnotatedBeanDefinitionReader#doRegisterBean 方法.

    进方法时, beanClass 是 StartConfig, 其他参数都是 null.

    /**
     * Register a bean from the given bean class, deriving its metadata from
     * class-declared annotations.
     * @param beanClass the class of the bean
     * @param instanceSupplier a callback for creating an instance of the bean
     * (may be {@code null})
     * @param name an explicit name for the bean
     * @param qualifiers specific qualifier annotations to consider, if any,
     * in addition to qualifiers at the bean class level
     * @param definitionCustomizers one or more callbacks for customizing the
     * factory's {@link BeanDefinition}, e.g. setting a lazy-init or primary flag
     * @since 5.0
     */
    <T> void doRegisterBean(Class<T> beanClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
            @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
        /**
         * 根据指定的bean创建一个AnnotatedGenericBeanDefinition, 从字面意思可以理解为 一般注解bd
         * AnnotatedGenericBeanDefinition包含了类的其他信息,比如一些元信息, scope, lazy等等
         */
        AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
        /**
         * 判断这个类是否需要跳过解析
         * 通过代码可以知道spring判断是否跳过解析,主要判断类有没有加注解
         */
        if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
            return;
        }
    
        abd.setInstanceSupplier(instanceSupplier);
        //得到类的作用域
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
        //把类的作用域添加到数据结构结构中
        abd.setScope(scopeMetadata.getScopeName());
        //生成类的名字 通过beanNameGenerator
        String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
        /**
         * 处理类当中的通用注解
         * 主要解析 Lazy DependsOn Primary Role 
         * 处理完成之后processCommonDefinitionAnnotations中依然是把他添加到 abd 中
         */
        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
        /**
         * 如果在向容器注册注解Bean定义时,使用了额外的限定符注解则解析
         * 关于Qualifier和Primary前面的课当中讲过,主要涉及到spring的自动装配
         * 这里需要注意的
         * byName和qualifiers这个变量是Annotation类型的数组,里面存不仅仅是Qualifier注解
         * 理论上里面里面存的是一切注解,所以可以看到下面的代码spring去循环了这个数组
         * 然后依次判断了注解当中是否包含了Primary,是否包含了Lazy
         */
        if (qualifiers != null) {
            for (Class<? extends Annotation> qualifier : qualifiers) {
                //如果配置了@Primary注解,则作为首选
                if (Primary.class == qualifier) {
                    abd.setPrimary(true);
                }
                //懒加载
                else if (Lazy.class == qualifier) {
                    abd.setLazyInit(true);
                }
                else {
                    //如果使用了除@Primary和@Lazy以外的其他注解,则为该Bean添加一个根据名字自动装配的限定符
                    abd.addQualifier(new AutowireCandidateQualifier(qualifier));
                }
            }
        }
        //自定义注解
        for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
            customizer.customize(abd);
        }
    
        //这里 BeanDefinitionHolder 对 BeanDefinition 和 beanName 进行了封装
        //对 applyScopedProxyMode 有作用, 对 registerBeanDefinition 没啥作用
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    
        /**
         * ScopedProxyMode 这个知识点比较复杂,需要结合 web去理解
         */
        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    
        /**
         * 把上述的这个数据结构注册给registry
         * registy就是AnnotatonConfigApplicationContext
         * AnnotatonConfigApplicationContext在初始化的時候通過調用父類的构造方法
         * 实例化了一个DefaultListableBeanFactory
         * registerBeanDefinition里面就是把definitionHolder这个数据结构包含的信息注册到
         * DefaultListableBeanFactory这个工厂
         */
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    }

    这里主要就是解析 配置类, 设置一些默认配置. 将最后的结果封装到 abd (AnnotatedGenericBeanDefinition) 中, 然后通过 registerBeanDefinition 方法, 注册到容器中.

    registerBeanDefinition方法不但会注册 bean 的名字, 还会对别名进行注册. 别名可以不用管. 主要是调用了

    org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition 方法, 内容如下: 

    /**
     * 通过 this.beanDefinitionMap.put(beanName, beanDefinition) 进行 bean 的注册
     */
    @Override
    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 {
                ((AbstractBeanDefinition) beanDefinition).validate();
            }
            catch (BeanDefinitionValidationException ex) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                        "Validation of bean definition failed", ex);
            }
        }
    
        BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
        if (existingDefinition != null) {
            if (!isAllowBeanDefinitionOverriding()) {
                throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
            }
            else if (existingDefinition.getRole() < beanDefinition.getRole()) {
                // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
                if (logger.isInfoEnabled()) {
                    logger.info("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.isDebugEnabled()) {
                    logger.debug("Overriding bean definition for bean '" + beanName +
                            "' with a different definition: replacing [" + existingDefinition +
                            "] with [" + beanDefinition + "]");
                }
            }
            else {
                if (logger.isTraceEnabled()) {
                    logger.trace("Overriding bean definition for bean '" + beanName +
                            "' with an equivalent definition: replacing [" + existingDefinition +
                            "] with [" + beanDefinition + "]");
                }
            }
            this.beanDefinitionMap.put(beanName, beanDefinition);
        }
        else {
            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;
                    removeManualSingletonName(beanName);
                }
            }
            else {
                // Still in startup registration phase
                this.beanDefinitionMap.put(beanName, beanDefinition);
                this.beanDefinitionNames.add(beanName);
                removeManualSingletonName(beanName);
            }
            this.frozenBeanDefinitionNames = null;
        }
    
        if (existingDefinition != null || containsSingleton(beanName)) {
            resetBeanDefinition(beanName);
        }
    }

    从源码上看, register 方法, 主要就是解析 配置类, 将配置类转换成 BeanDefinition, 设置一些默认属性, 然后注册到 spring (BeanFactory) 容器中.

    特别需要注意的是, 此时配置类, 并没有被创建出来, 只是解析了一番, 相当于是给 spring 写了一份说明. 后面 spring 会根据这份说明, 来创建和解析配置类.

  • 相关阅读:
    确定比赛名次
    What Are You Talking About
    小兔的棋盘
    How Many Answers Are Wrong
    备份当前的ubuntu系统生成iso
    eclipse导入maven项目有时出现web.xml is missing的问题
    eclipse自动添加版权信息
    javac不是内部或外部命令
    linux目录权限
    python import error:no module named yaml
  • 原文地址:https://www.cnblogs.com/elvinle/p/13229390.html
Copyright © 2011-2022 走看看