加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

【转】Spring注解扫描原理2/2

(2022-04-22 12:00:24)
分类: JAVA开发

原文:https://www.it610.com/article/1495559602308186112.htm


Spring注解扫描原理浅析

4、ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,

PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {

    @Override

    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {

        // 省略...

        processConfigBeanDefinitions(registry);

    }}

进入processConfigBeanDefinitions方法

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {

 

// 省略...

do {

        // 通过pase方法解析配置类,其实也就是在这个方法中去做的Spring的扫描

        parser.parse(candidates);

        parser.validate();

 

        Set configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());

        configClasses.removeAll(alreadyParsed);

 

        // Read the model and create bean definitions based on its content

        if (this.reader == null) {

            this.reader = new ConfigurationClassBeanDefinitionReader(

                    registry, this.sourceExtractor, this.resourceLoader, this.environment,

                    this.importBeanNameGenerator, parser.getImportRegistry());

        }

        this.reader.loadBeanDefinitions(configClasses);

        alreadyParsed.addAll(configClasses);

 

        candidates.clear();

        if (registry.getBeanDefinitionCount() > candidateNames.length) {

            String[] newCandidateNames = registry.getBeanDefinitionNames();

            Set oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));

            Set alreadyParsedClasses = new HashSet<>();

            for (ConfigurationClass configurationClass : alreadyParsed) {

                alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());

            }

            for (String candidateName : newCandidateNames) {

                // 找出所有没有被解析过的配置类

                if (!oldCandidateNames.contains(candidateName)) {

                    BeanDefinition bd = registry.getBeanDefinition(candidateName);

                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&

                            !alreadyParsedClasses.contains(bd.getBeanClassName())) {

                        candidates.add(new BeanDefinitionHolder(bd, candidateName));

                    }

                }

            }

            candidateNames = newCandidateNames;

        }

    }

    while (!candidates.isEmpty());}

接着进入parse方法

public void parse(Set configCandidates) {

   // 省略...

   // 解析通过注解得到的Bean

   parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());

   // 省略...    }

进入到解析AnnotatedBeanDefinitionparse方法中,然后再进入processConfigurationClass方法

protected void processConfigurationClass(ConfigurationClass configClass, Predicate filter) throws IOException {

    if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {

        return;

    }

 

    // 用ConfigurationClass保存配置类种的信息

    ConfigurationClass existingClass = this.configurationClasses.get(configClass);

    if (existingClass != null) {

        if (configClass.isImported()) {

            if (existingClass.isImported()) {

                existingClass.mergeImportedBy(configClass);

            }

            // Otherwise ignore new imported config class; existing non-imported class overrides it.

            return;

        }

        else {

            // Explicit bean definition found, probably replacing an import.

            // Let's remove the old one and go with the new one.

            this.configurationClasses.remove(configClass);

            this.knownSuperclasses.values().removeIf(configClass::equals);

        }

    }

 

    // 在此处递归地处理配置类及其超类层次结构

    // Recursively process the configuration class and its superclass hierarchy.

    SourceClass sourceClass = asSourceClass(configClass, filter);

    do {

        // doProcessConfigurationClass中会解析配置类上的注解

        sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);

    }

    while (sourceClass != null);

 

    this.configurationClasses.put(configClass, configClass);}

接着进入到进入到doProcessConfigurationClass中就会看到核心代码了

protected final SourceClass doProcessConfigurationClass(

        ConfigurationClass configClass, SourceClass sourceClass, Predicate filter)

        throws IOException {

 

    // 如果加了@Component注解就会首先递归地处理内部类

    if (configClass.getMetadata().isAnnotated(Component.class.getName())) {

        // Recursively process any member (nested) classes first

        processMemberClasses(configClass, sourceClass, filter);

    }

 

    // 解析@PropertySource注解

    // Process any @PropertySource annotations

    for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(

            sourceClass.getMetadata(), PropertySources.class,

            org.springframework.context.annotation.PropertySource.class)) {

        if (this.environment instanceof ConfigurableEnvironment) {

            // 处理注解中的内容,并抽象成PropertySource对象

            processPropertySource(propertySource);

        }

        else {

            logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +

                    "]. Reason: Environment must implement ConfigurableEnvironment");

        }

    }

 

    // 开始解析@ComponentScans和@ComponentScan注解

    // Process any @ComponentScan annotations

    Set componentScans = AnnotationConfigUtils.attributesForRepeatable(

            sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);

    if (!componentScans.isEmpty() &&

            !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {

        for (AnnotationAttributes componentScan : componentScans) {

            // The config class is annotated with @ComponentScan -> perform the scan immediately

            Set scannedBeanDefinitions =

                    this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());

            // Check the set of scanned definitions for any further config classes and parse recursively if needed

            for (BeanDefinitionHolder holder : scannedBeanDefinitions) {

                BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();

                if (bdCand == null) {

                    bdCand = holder.getBeanDefinition();

                }

                if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {

                    parse(bdCand.getBeanClassName(), holder.getBeanName());

                }

            }

        }

    }

 

    // 解析@Import注解

    // Process any @Import annotations

    processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

 

    // 解析@ImportResource注解

    // Process any @ImportResource annotations

    AnnotationAttributes importResource =

            AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);

    if (importResource != null) {

        String[] resources = importResource.getStringArray("locations");

        Class

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有