• ConfigurationClassPostProcessor类的processConfigBeanDefinitions方法源码解析


    spring版本为5.0.11

    ConfigurationClassPostProcessor类处理带有@Configuration配置类,使用方法processConfigBeanDefinitions
    public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
            //1.初始化BeanDefinitionHolder集合
            List<BeanDefinitionHolder> configCandidates = new ArrayList();
            //2.所有已经注册的bean 
            String[] candidateNames = registry.getBeanDefinitionNames();
            String[] var4 = candidateNames;
            int var5 = candidateNames.length;
            //3.遍历已注册的bean数组
            for(int var6 = 0; var6 < var5; ++var6) {
                //bean名称
                String beanName = var4[var6];
                //得到BeanDefinition实例
                BeanDefinition beanDef = registry.getBeanDefinition(beanName);
                //判断:full configuration 和 lite configuration
                //参照https://www.cnblogs.com/mufeng07/p/12163442.html
                if (!ConfigurationClassUtils.isFullConfigurationClass(beanDef) && !ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
                    //带有@Configuration注解的bean,beanDef的属性设置为full,beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, "full");
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                        //带有@Configuration注解的bean添加到集合中
                        configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
                    }
                } else if (this.logger.isDebugEnabled()) {
                //两种都不满足,配置类已经被处理了
                    this.logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
                }
            }
            //集合非空
            if (!configCandidates.isEmpty()) {
                // 多个Java配置类,按@Ordered注解排序
                configCandidates.sort((bd1, bd2) -> {
                    int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
                    int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
                    return Integer.compare(i1, i2);
                });
                //检测通过封闭的应用程序上下文提供的任何自定义bean名称生成策略
                //暂时不理解
                SingletonBeanRegistry sbr = null;
                if (registry instanceof SingletonBeanRegistry) {
                    sbr = (SingletonBeanRegistry)registry;
                    if (!this.localBeanNameGeneratorSet) {
                        BeanNameGenerator generator = (BeanNameGenerator)sbr.getSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator");
                        if (generator != null) {
                            this.componentScanBeanNameGenerator = generator;
                            this.importBeanNameGenerator = generator;
                        }
                    }
                }
                //web应用为StandardServletEnvironment
                if (this.environment == null) {
                    this.environment = new StandardEnvironment();
                }
                //初始化一个ConfigurationClassParser解析器,可以解析@Congiguration配置类
                ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry);
                //List转成Set
                Set<BeanDefinitionHolder> candidates = new LinkedHashSet(configCandidates);
                //初始化一个已经解析的HashSet
                HashSet alreadyParsed = new HashSet(configCandidates.size());
                //循环解析,直到candidates为空
                do {
                    //核心:解析
                    parser.parse(candidates);
                    //主要校验配置类不能使用final修饰符(CGLIB代理是生成一个子类,因此原先的类不能使用final修饰)
                    //if (this.getMetadata().isAnnotated(Configuration.class.getName()) && this.getMetadata().isFinal()) 
                    parser.validate();
                    //排除已处理过的配置类
                    Set<ConfigurationClass> configClasses = new LinkedHashSet(parser.getConfigurationClasses());
                    configClasses.removeAll(alreadyParsed);
                    //读取模型并根据其内容创建bean定义
                    if (this.reader == null) {
                        this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry());
                    }
                    //2.加载bean定义信息,主要实现将@Configuration @Import @ImportResource @ImportRegistrar注册为bean
                    this.reader.loadBeanDefinitions(configClasses);
                    //将configClasses加入到已解析alreadyParsed中
                    alreadyParsed.addAll(configClasses);
                    //清空已处理的配置类
                    candidates.clear();
                    //再次获取容器中bean定义数量  如果大于 之前获取的bean定义数量,则说明有新的bean注册到容器中,需要再次解析
                    ///getBeanDefinitionCount()取得是registry.beanDefinitionMap.size()
                    if (registry.getBeanDefinitionCount() > candidateNames.length) {
                        //容器中新的所有已注册的bean(包括老的)
                        String[] newCandidateNames = registry.getBeanDefinitionNames();
                        //容器中老的已注册的bean(已经解析了)
                        Set<String> oldCandidateNames = new HashSet(Arrays.asList(candidateNames));
                        //用来存储已经解析的类
                        Set<String> alreadyParsedClasses = new HashSet();
                        Iterator var12 = alreadyParsed.iterator();
                        //循环遍历把已解析的类放到alreadyParsedClasses中
                        while(var12.hasNext()) {
                            ConfigurationClass configurationClass = (ConfigurationClass)var12.next();
                            alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
                        }
    
                        String[] var23 = newCandidateNames;
                        int var24 = newCandidateNames.length;
                        //循环遍历新的所有已注册的bean,排除老的已解析的,再过滤是否是配置类带有@Configuration,并且没有解析过,添加到candidates中,
                        //下一次可以再处理解析
                        for(int var14 = 0; var14 < var24; ++var14) {
                            String candidateName = var23[var14];
                            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());
                //// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
                if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
                    sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
                }
    
                if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
                     // Clear cache in externally provided MetadataReaderFactory; this is a no-op
                     // for a shared cache since it'll be cleared by the ApplicationContext.
                    ((CachingMetadataReaderFactory)this.metadataReaderFactory).clearCache();
                }
    
            }
        }
    核心:如何进行解析ConfigurationClassParser类,parser.parse(candidates)
    接下来可以参照https://www.cnblogs.com/mufeng07/p/12172549.html进行理解

  • 相关阅读:
    linux系统编程之信号(八):三种时间结构及定时器setitimer()详解
    linux系统编程之信号(七):被信号中断的系统调用和库函数处理方式
    linux系统编程之信号(六):信号发送函数sigqueue和信号安装函数sigaction
    吃透Javascript数组操作的正确姿势—再读《Js高程》
    Sublime Text3 配置Node.js运行命令
    前端性能优化规则总结—读《高性能网站建设指南》
    常见IE浏览器bug及其修复方案(双外边距、3像素偏移、绝对定位)
    常见布局修复方案—外边距叠加问题
    常见布局修复方案—选择器特殊性问题
    Hexo静态博客搭建教程
  • 原文地址:https://www.cnblogs.com/mufeng07/p/12165616.html
Copyright © 2020-2023  润新知