Spring的BeanDefinition其他Reader2

ConfigurationClassParser

ConfigurationClassParser的作用是解析被@Configuration注解标注的类。

用户使用@Configuration标注的类,会被解析为ConfigurationClass,然后ConfigurationClassBeanDefinitionReader从ConfigurationClass中解析出BeanDefinition。

ConfigurationClassParser是在ConfigurationClassPostProcessor中被使用,而ConfigurationClassPostProcessor这个BeanFactoryPostProcessor是当发现xml文件中含有以下标签时被注册的:

<context:annotation-config/> or
<context:component-scan/>

ConfigurationClassPostProcessor中的处理逻辑为:

  • 检查BeanDefinition是否为配置类,有两种配置类

    • full是指:类上标注了@Configration

    • lite是指:类上标注了@Import或者类中含有标注了@Bean的方法

  • 因为涉及到配置类的覆盖问题,对发现的配置类进行排序

  • 从每一个配置类中解析出BeanDefinition,如果解析出的BeanDefinition仍然为配置类,则继续解析该配置类。

其中,每一个配置类中解析出BeanDefinition的主要代码如下:

ConfigurationClassParser parser = new ConfigurationClassParser(
                this.metadataReaderFactory, 
                this.problemReporter, 
                this.environment,
                this.resourceLoader, 
                this.componentScanBeanNameGenerator, 
                registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
do {
    //从当前配置类拿到ConfigurationClass对象
    parser.parse(candidates);
    parser.validate();
    Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
    //从ConfigurationClass对象中解析出BeanDefinition
    if (this.reader == null) {
        this.reader = new ConfigurationClassBeanDefinitionReader(
                registry, this.sourceExtractor, this.resourceLoader, this.environment,
                this.importBeanNameGenerator, parser.getImportRegistry());
    }
    this.reader.loadBeanDefinitions(configClasses);

}
while (!candidates.isEmpty());

从一个配置类可能获取到多个ConfigurationClass对象,比如配置类上通过@Import标签引入了其他配置类。

可以看出,ConfigurationClassParser这个BeanDefinitonReader是比前面提到的ClassPathBeanDefinitionScanner更为上层的封装,它可以完整地解析出几乎所有的注解。

参考

一分钟学会spring注解之@Import注解

【译】Spring 4 @PropertySource和@Value注解示例

Java inner class and static nested class

Spring(32)——ImportSelector介绍

Last updated