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

77 阅读2分钟

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));
  • 设置实例的创建方式(abd.setInstanceSupplier(supplier)

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

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

    也就是实例单例还是多例

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

AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

解析注解元数据中的注定注解,并设置到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));
        }
    }
}

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

  • 懒加载 @Lazy

  • 优先级 @Primary

5、封装BeanDefinitionHolder

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

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

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

BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);

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

7、小结

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