• 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)中。

  • 相关阅读:
    java基于springboot教学评价管理系统附源码
    Databend 源码阅读:配置管理
    基于Python实现的快递管理系统源码+数据库,采用PyQt6实现GUI界面
    实现微信扫码自动登陆与注册功能
    ftp发布服务器
    登录系统的时候账号和密码加密传输
    Nginx负载均衡
    C++ Reference: Standard C++ Library reference: Containers: list: list: size
    windows英伟达nvidia显卡驱动安装教程
    Docker教程实操入门---如何启动一个已经停止的容器
  • 原文地址:https://blog.csdn.net/static_coder/article/details/134075453