spring IOC - AnnotationConfigApplicationContext#register(StartConfig.class)

接着上一篇. 这里来看一下 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
 */
 void doRegisterBean(Class beanClass, @Nullable Supplier instanceSupplier, @Nullable String name,
        @Nullable Classextends 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 (Classextends 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 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 会根据这份说明, 来创建和解析配置类.

 

你可能感兴趣的:(spring IOC - AnnotationConfigApplicationContext#register(StartConfig.class))