• SpringBoot 刷新上下文2--执行BeanDefinitionRegistryPostProcessor


    SpringBoot刷新上下文一共七篇,基于SpringBoot 2.2.7.RELEASE,Spring 5.2.6.RELEASE
    SpringBoot 刷新上下文1–主流程
    SpringBoot 刷新上下文2–执行BeanDefinitionRegistryPostProcessor
    SpringBoot 刷新上下文3–解析引导类
    SpringBoot 刷新上下文4–处理ComponentScan
    SpringBoot 刷新上下文5–处理其他注解
    SpringBoot 刷新上下文6–加载并注册BeanDefinition
    SpringBoot 刷新上下文7–执行BeanFactoryPostProcessor

    2.1、ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry 处理IOC

    接前篇,调用BeanDefinitionRegistryPostProcessors,这里主要是执行了ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry 。

    //org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors
    private static void invokeBeanDefinitionRegistryPostProcessors(
        Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
    	//ConfigrationClassPostProsessor
        for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
            postProcessor.postProcessBeanDefinitionRegistry(registry);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    private final Set<Integer> registriesPostProcessed = new HashSet<>();
    //org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        int registryId = System.identityHashCode(registry);
        // 这里做了一个防重
        if (this.registriesPostProcessed.contains(registryId)) {
            throw new IllegalStateException(
                "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
        }
        if (this.factoriesPostProcessed.contains(registryId)) {
            throw new IllegalStateException(
                "postProcessBeanFactory already called on this post-processor against " + registry);
        }
        // 加入缓存
        this.registriesPostProcessed.add(registryId);
    
        processConfigBeanDefinitions(registry);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    处理配置类

    private ConfigurationClassBeanDefinitionReader reader;
    //org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions
    public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
        //候选的配置类 BeanDefinitionHolder 集合
        List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
        //获取候选BeanDefinitionName	这里包含引导类 其他类BeanN都是全名,是Spring内置配置类
        //candidateNames = {String[7]@4153} 
    	// 0 = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"
    	// 1 = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"
    	// 2 = "org.springframework.context.annotation.internalCommonAnnotationProcessor"
    	// 3 = "org.springframework.context.event.internalEventListenerProcessor"
    	// 4 = "org.springframework.context.event.internalEventListenerFactory"
    	// 5 = "Application"
    	// 6 = "org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory"
        String[] candidateNames = registry.getBeanDefinitionNames();
        for (String beanName : candidateNames) {
            BeanDefinition beanDef = registry.getBeanDefinition(beanName);
            if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
                }
            }
            //检查是不是候选类,就是被一些注解标注的类
            else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
            }
        }
    
        // Return immediately if no @Configuration classes were found
        // 候选类是否为空,这里含有引导类,所以不为空
        if (configCandidates.isEmpty()) {
            return;
        }
    
        // Sort by previously determined @Order value, if applicable
        // 按 order 排序
        configCandidates.sort((bd1, bd2) -> {
            int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
            int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
            return Integer.compare(i1, i2);
        });
    
        // Detect any custom bean name generation strategy supplied through the enclosing application context
        SingletonBeanRegistry sbr = null;
        //registry = DefaultListableBeanFactory
        if (registry instanceof SingletonBeanRegistry) {
            sbr = (SingletonBeanRegistry) registry;
            if (!this.localBeanNameGeneratorSet) {
                //CONFIGURATION_BEAN_NAME_GENERATOR = "org.springframework.context.annotation.internalConfigurationBeanNameGenerator"
                BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
                    AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
                if (generator != null) {
                    this.componentScanBeanNameGenerator = generator;
                    this.importBeanNameGenerator = generator;
                }
            }
        }
    	//environment 已经初始化过了
        if (this.environment == null) {
            this.environment = new StandardEnvironment();
        }
    
        // Parse each @Configuration class
        // 创建Configuration 类的解析器 @Configuration 标注类
        ConfigurationClassParser parser = new ConfigurationClassParser(
            this.metadataReaderFactory, this.problemReporter, this.environment,
            this.resourceLoader, this.componentScanBeanNameGenerator, registry);
    	//候选类 配置类 包括引导类
        Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
        // 已经解析,注册的类
        Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
        do {
            //解析 @Configuration 标注类,这里会解析引导类
            parser.parse(candidates);
            //处理 error 等 problemReporter
            parser.validate();
    		//已经解析的类
            Set<ConfigurationClass> 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<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
                Set<String> 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());
    
        // 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();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126

    这里会先检查候选类,如果候选类为空,则结束。

    解析候选类,包括Spring内建Bean和SpringBoot的引导类。

    加载并注册。

    2.1.1、判断是否候选类

    //org.springframework.context.annotation.ConfigurationClassUtils#checkConfigurationClassCandidate
    public static boolean checkConfigurationClassCandidate(
    			BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
    	//获取Class名称,这里还是处理的引导类
        String className = beanDef.getBeanClassName();
        if (className == null || beanDef.getFactoryMethodName() != null) {
            return false;
        }
    
        AnnotationMetadata metadata;
        //是否是被注解标注类
        if (beanDef instanceof AnnotatedBeanDefinition &&
            className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
            // Can reuse the pre-parsed metadata from the given BeanDefinition...
            // 获取注解元信息
            metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
        }
        else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
            // Check already loaded Class if present...
            // since we possibly can't even load the class file for this Class.
            Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
            if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||
                BeanPostProcessor.class.isAssignableFrom(beanClass) ||
                AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
                EventListenerFactory.class.isAssignableFrom(beanClass)) {
                return false;
            }
            metadata = AnnotationMetadata.introspect(beanClass);
        }
        else {
            try {
                MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
                metadata = metadataReader.getAnnotationMetadata();
            }
            catch (IOException ex) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Could not find class file for introspecting configuration annotations: " +
                                 className, ex);
                }
                return false;
            }
        }
    	//获取 @Configuration 标注元信息
        Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
        //proxyBeanMethods 属性不为空
        if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
            //org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass
            //full
            beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
        }
        // 被其他注解标注
        else if (config != null || isConfigurationCandidate(metadata)) {
            //lite
            beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
        }
        else {
            return false;
        }
    
        // It's a full or lite configuration candidate... Let's determine the order value, if any.
        //获取 order
        Integer order = getOrder(metadata);
        if (order != null) {
            beanDef.setAttribute(ORDER_ATTRIBUTE, order);
        }
    
        return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

    这个方法判断如果类没有被注解标注,就返回false。

    引导类是被 @SpringBootApplication标注的,@SpringBootApplication 被@SpringBootConfiguration 标注,@SpringBootConfiguration 被 @Configuration 标注,所以引导类是候选类。

    @Configuration注解中proxyBeanMethods 默认是true,所以引导类BeanDefinition属性中org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass 是 full。

    如果@Configuration 注解 proxyBeanMethods 设置成false,则不是候选类,否则会判断是否被下面的五个注解(@Component, @ComponentScan, @Import, @ImportResource, @Bean)标注,如果被下面的五个注解标注了,也是候选类,BeanDefinition属性中org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass 是 lite。

    2.1.1.1、判断是否被其他注解标注
    private static final Set<String> candidateIndicators = new HashSet<>(8);
    static {
        candidateIndicators.add(Component.class.getName());
        candidateIndicators.add(ComponentScan.class.getName());
        candidateIndicators.add(Import.class.getName());
        candidateIndicators.add(ImportResource.class.getName());
    }
    //org.springframework.context.annotation.ConfigurationClassUtils#isConfigurationCandidate
    public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
        // Do not consider an interface or an annotation...
        if (metadata.isInterface()) {
            return false;
        }
    
        // Any of the typical annotations found?
        for (String indicator : candidateIndicators) {
            if (metadata.isAnnotated(indicator)) {
                return true;
            }
        }
    
        // Finally, let's look for @Bean methods...
        try {
            return metadata.hasAnnotatedMethods(Bean.class.getName());
        }
        catch (Throwable ex) {
            if (logger.isDebugEnabled()) {
                logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex);
            }
            return false;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    2.1.1.2、获取order
    //org.springframework.context.annotation.ConfigurationClassUtils#getOrder(org.springframework.core.type.AnnotationMetadata)
    public static Integer getOrder(AnnotationMetadata metadata) {
        Map<String, Object> orderAttributes = metadata.getAnnotationAttributes(Order.class.getName());
        return (orderAttributes != null ? ((Integer) orderAttributes.get(AnnotationUtils.VALUE)) : null);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.1.2、创建配置类解析器

    //元数据读取器工厂
    private final MetadataReaderFactory metadataReaderFactory;
    //spi 处理error 和 warn
    private final ProblemReporter problemReporter;
    private final Environment environment;
    private final ResourceLoader resourceLoader;
    private final BeanDefinitionRegistry registry;
    //扫描注解解析器
    private final ComponentScanAnnotationParser componentScanParser;
    //condition 解析器
    private final ConditionEvaluator conditionEvaluator;
    public ConfigurationClassParser(MetadataReaderFactory metadataReaderFactory, ProblemReporter problemReporter, Environment environment, ResourceLoader resourceLoader, BeanNameGenerator componentScanBeanNameGenerator, BeanDefinitionRegistry registry) {
    
        this.metadataReaderFactory = metadataReaderFactory;
        this.problemReporter = problemReporter;
        this.environment = environment;
        this.resourceLoader = resourceLoader;
        this.registry = registry;
        this.componentScanParser = new ComponentScanAnnotationParser(
            environment, resourceLoader, componentScanBeanNameGenerator, registry);
        this.conditionEvaluator = new ConditionEvaluator(registry, environment, resourceLoader);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
  • 相关阅读:
    企业网络革命:连接和访问的智慧选项
    plt函数显示图片 & 在图片上画边界框 & 边界框坐标转换
    AutoCAD的各种方法
    django之day01
    卷积层数量过多的缺点,卷积积分的被积函数
    虚拟桌宠模拟器:VPet-Simulator,一个开源的桌宠软件, 可以内置到任何WPF应用程序
    电商类面试问题--01Elasticsearch与Mysql数据同步问题
    Hdu 3549 Flow Problem(最大流)
    CenterPoint 工程复现
    7.6中间件
  • 原文地址:https://blog.csdn.net/xuwenjingrenca/article/details/126574313