• Spring源码解析-注册配置信息


    1、注册方法概述

    register(componentClasses) 注册配置类的信息。其中componentClasses 为传入的配置类class。

    通过AnnotatedBeanDefinitionReaderregister(this.reader.register(componentClasses))方法。AnnotatedBeanDefinitionReader 已经注册了系统自带的处理器以及方法。就可以直接解析配置类中的属性和方法了。最终调用的是org.springframework.context.annotation.AnnotatedBeanDefinitionReader#doRegisterBean方法,遍历配置类以此处理。

    主要处理的流程如下:

    • 读取配置类的信息,将信息封装到AnnotatedGenericBeanDefinition 对象中。

    • 通过注解工具处理AnnotatedGenericBeanDefinition 中的注解。

    • 将配置类的AnnotatedGenericBeanDefinitionbeanName 封装成BeanDefinitionHolder

    • BeanDefinitionHolder 注册到BeanDefinitionRegistry中,也就是当前的context(AnnotationConfigApplicationContext)中。

    2、读取配置类的信息

    主要方法:new AnnotatedGenericBeanDefinition(beanClass)

    该方法主要获取配置类注解的元数据(AnnotationMetadata),只是获取不做任何处理。

    该对象内部主要保存两个对象:

    • 配置类的Class对象(Object beanClass

    • 配置类的注解元数据AnnotationMetadata metadata

    • setBeanClass(beanClass) 将当前的配置类交给AnnotatedGenericBeanDefinition 对象

    • this.metadata = AnnotationMetadata.introspect(beanClass) 通过AnnotationMetadata静态方法获取配置类的注解元数据

    3、设置配置类的其他属性

    abd.setInstanceSupplier(supplier);
    ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
    abd.setScope(scopeMetadata.getScopeName());
    String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
    
    • 1
    • 2
    • 3
    • 4
    • 设置实例的创建方式(abd.setInstanceSupplier(supplier)

      supplier 参数默认为空,该参数可以将实例对象交给Spring管理,不需要遵守Bean严格的创建过程

    • 设置实例的作用域(abd.setScope(scopeMetadata.getScopeName())

      也就是实例单例还是多例

    4、通过注解工具处理AnnotatedGenericBeanDefinition 中的注解

    AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
    
    • 1

    解析注解元数据中的注定注解,并设置到Bean定义的属性中

    处理的注解:

    • 懒加载 @Lazy

    • 优先级 @Primary

    • 依赖条件 @DependsOn

    • 角色 @Role

    • 描述 @Description

    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));
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    如果 qualifier 参数有值,则优先获取qualifier 中的属性并覆盖上面的值,包含的注解:

    • 懒加载 @Lazy

    • 优先级 @Primary

    5、封装BeanDefinitionHolder

    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    
    • 1
    • 2

    将BeanName和Bean的定义信息封装成新的对象。如果是代理对象则按照代理对象封装BeanDefinitionHolder

    6、Bean定义信息注册到当前的Context

    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    
    • 1

    注册信息主要是三个属性beanDefinitionbeanNamealiases。将这些属性注册到当前的Context(registry)中

    7、小结

    注册配置的方法很简单,就是解析配置的注解信息,并装所有的注解信息、Bean的名称、别名注册到AnnotationConfigApplicationContext(registry)中。

  • 相关阅读:
    《SpringBoot篇》16.SpringBoot整合Elasticsearch超详细教程
    RepVGG网络学习记录
    【会议资源】2022年第三届自动化科学与工程国际会议(JCASE 2022)
    看懂这篇文章-你就懂了数据库死锁产生的场景和解决方法
    类与对象(1)
    拥有这个中文版CustomGPT,你也能定制自己的AI问答机器人
    ThreadLocal原理
    神奇代码备份恢复工具逸事与操作指南
    XSAN数据恢复-存储空间架构迁移时误格式化存储系统的XSAN数据恢复案例
    数据结构与算法-栈
  • 原文地址:https://blog.csdn.net/static_coder/article/details/134075453