• SpringBoot 刷新上下文6--加载并注册BeanDefinition


    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.4、加载并注册BeanDefinition

    //org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitions
    public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
        TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
        //循环所有的配置类
        for (ConfigurationClass configClass : configurationModel) {
            loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    private final ImportRegistry importRegistry;
    //org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass
    private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
        //是否应该跳过	Condition的一些列注解
        if (trackedConditionEvaluator.shouldSkip(configClass)) {
            //获取配置类的名称
            String beanName = configClass.getBeanName();
            if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
                //将配置类从ioc中移除
                this.registry.removeBeanDefinition(beanName);
            }
            //将配置类移除
            this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
            return;
        }
    	//加载导入类
        if (configClass.isImported()) {
            registerBeanDefinitionForImportedConfigurationClass(configClass);
        }
        //加载@Bean标注的方法
        for (BeanMethod beanMethod : configClass.getBeanMethods()) {
            loadBeanDefinitionsForBeanMethod(beanMethod);
        }
    	//加载导入资源
        loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
        //加载Registrar
         loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
    }
    
    • 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
    2.1.4.1、处理导入类
    //org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsFromRegistrars
    private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
        //遍历所有ImportBeanDefinitionRegistrar的实现类
        registrars.forEach((registrar, metadata) ->
                           registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    //org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#registerBeanDefinitionForImportedConfigurationClass
    private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
        //获取配置类的注解元数据
        AnnotationMetadata metadata = configClass.getMetadata();
        //创建BeanDefinition
        AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
    	//解析Scope
        ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
        configBeanDef.setScope(scopeMetadata.getScopeName());
        //获取BeanName
        String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
        //处理通用注解
        AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);
    	//创建BeanDefinitionHolder
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
        //注册配置类 registry = DefaultListableBeanFactory
        this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
        configClass.setBeanName(configBeanName);
    
        if (logger.isTraceEnabled()) {
            logger.trace("Registered bean definition for imported class '" + configBeanName + "'");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    2.1.4.2、处理@Bean标注的方法
    //org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForBeanMethod
    private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
        ConfigurationClass configClass = beanMethod.getConfigurationClass();
        MethodMetadata metadata = beanMethod.getMetadata();
        String methodName = metadata.getMethodName();
    
        // Do we need to mark the bean as skipped by its condition?
        //是否应该跳过	Condition一系列注解
        if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
            configClass.skippedBeanMethods.add(methodName);
            return;
        }
        if (configClass.skippedBeanMethods.contains(methodName)) {
            return;
        }
    	//获取@Bean的注解属性
        AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
        Assert.state(bean != null, "No @Bean annotation attributes");
    
        // Consider name and any aliases
        //bean的别名
        List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
        //bean的名称,@bean配置了名称,取第一个,没有配置,取方法名
        String beanName = (!names.isEmpty() ? names.remove(0) : methodName);
    
        // Register aliases even when overridden
        // 注册别名
        for (String alias : names) {
            this.registry.registerAlias(beanName, alias);
        }
    	
        // Has this effectively been overridden before (e.g. via XML)?
        // bean是否允许覆盖
        if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
            if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {
                throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
                                                       beanName, "Bean name derived from @Bean method '" + beanMethod.getMetadata().getMethodName() +
                                                       "' clashes with bean name for containing configuration class; please make those names unique!");
            }
            return;
        }
    	//创建BeanDefinition,下面会配置BeanDefinition
        ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
        beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
    
        // @Bean 的方法是静态方法
        if (metadata.isStatic()) {
            // static @Bean method
            if (configClass.getMetadata() instanceof StandardAnnotationMetadata) {
                beanDef.setBeanClass(((StandardAnnotationMetadata) configClass.getMetadata()).getIntrospectedClass());
            }
            else {
                beanDef.setBeanClassName(configClass.getMetadata().getClassName());
            }
            beanDef.setUniqueFactoryMethodName(methodName);
        }
        else {// @Bean 的方法是实例方法
            // instance @Bean method
            beanDef.setFactoryBeanName(configClass.getBeanName());
            beanDef.setUniqueFactoryMethodName(methodName);
        }
    
        if (metadata instanceof StandardMethodMetadata) {
            beanDef.setResolvedFactoryMethod(((StandardMethodMetadata) metadata).getIntrospectedMethod());
        }
    	// 构造器自动注入
        beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
        //SKIP_REQUIRED_CHECK_ATTRIBUTE = org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.skipRequiredCheck
        beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
    	//处理通用注解
        AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
    
        Autowire autowire = bean.getEnum("autowire");
        if (autowire.isAutowire()) {
            beanDef.setAutowireMode(autowire.value());
        }
    
        boolean autowireCandidate = bean.getBoolean("autowireCandidate");
        if (!autowireCandidate) {
            beanDef.setAutowireCandidate(false);
        }
    
        String initMethodName = bean.getString("initMethod");
        if (StringUtils.hasText(initMethodName)) {
            beanDef.setInitMethodName(initMethodName);
        }
    
        String destroyMethodName = bean.getString("destroyMethod");
        beanDef.setDestroyMethodName(destroyMethodName);
    
        // Consider scoping
        // 处理代理模式
        ScopedProxyMode proxyMode = ScopedProxyMode.NO;
        AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
        if (attributes != null) {
            beanDef.setScope(attributes.getString("value"));
            proxyMode = attributes.getEnum("proxyMode");
            if (proxyMode == ScopedProxyMode.DEFAULT) {
                proxyMode = ScopedProxyMode.NO;
            }
        }
    
        // Replace the original bean definition with the target one, if necessary
        BeanDefinition beanDefToRegister = beanDef;
        // 创建代理的BeanDefinition
        if (proxyMode != ScopedProxyMode.NO) {
            BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
                new BeanDefinitionHolder(beanDef, beanName), this.registry,
                proxyMode == ScopedProxyMode.TARGET_CLASS);
            beanDefToRegister = new ConfigurationClassBeanDefinition(
                (RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata);
        }
    
        if (logger.isTraceEnabled()) {
            logger.trace(String.format("Registering bean definition for @Bean method %s.%s()",
                                       configClass.getMetadata().getClassName(), beanName));
        }
        // 注册到ioc
        this.registry.registerBeanDefinition(beanName, beanDefToRegister);
    }
    
    • 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

    是否允许重写

    //org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#isOverriddenByExistingDefinition
    protected boolean isOverriddenByExistingDefinition(BeanMethod beanMethod, String beanName) {
        if (!this.registry.containsBeanDefinition(beanName)) {
            return false;
        }
    	//获得BeanDefinition
        BeanDefinition existingBeanDef = this.registry.getBeanDefinition(beanName);
    
        // Is the existing bean definition one that was created from a configuration class?
        // -> allow the current bean method to override, since both are at second-pass level.
        // However, if the bean method is an overloaded case on the same configuration class,
        // preserve the existing bean definition.
        if (existingBeanDef instanceof ConfigurationClassBeanDefinition) {
            ConfigurationClassBeanDefinition ccbd = (ConfigurationClassBeanDefinition) existingBeanDef;
            //class名称相同
            if (ccbd.getMetadata().getClassName().equals(
                beanMethod.getConfigurationClass().getMetadata().getClassName())) {
                //方法名称相同
                if (ccbd.getFactoryMethodMetadata().getMethodName().equals(ccbd.getFactoryMethodName())) {
                    ccbd.setNonUniqueFactoryMethodName(ccbd.getFactoryMethodMetadata().getMethodName());
                }
                return true;
            }
            else {
                return false;
            }
        }
    
        // A bean definition resulting from a component scan can be silently overridden
        // by an @Bean method, as of 4.2...
        if (existingBeanDef instanceof ScannedGenericBeanDefinition) {
            return false;
        }
    
        // Has the existing bean definition bean marked as a framework-generated bean?
        // -> allow the current bean method to override it, since it is application-level
        if (existingBeanDef.getRole() > BeanDefinition.ROLE_APPLICATION) {
            return false;
        }
    
        // At this point, it's a top-level override (probably XML), just having been parsed
        // before configuration class processing kicks in...
        //不允许覆盖,抛异常
        if (this.registry instanceof DefaultListableBeanFactory &&
            !((DefaultListableBeanFactory) this.registry).isAllowBeanDefinitionOverriding()) {
            throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
                                                   beanName, "@Bean definition illegally overridden by existing bean definition: " + existingBeanDef);
        }
        if (logger.isDebugEnabled()) {
            logger.debug(String.format("Skipping bean definition for %s: a definition for bean '%s' " +
                                       "already exists. This top-level bean definition is considered as an override.",
                                       beanMethod, beanName));
        }
        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
    2.1.4.3、处理ImportedResource
    //org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsFromImportedResources
    private void loadBeanDefinitionsFromImportedResources(
    			Map<String, Class<? extends BeanDefinitionReader>> importedResources) {
    
        Map<Class<?>, BeanDefinitionReader> readerInstanceCache = new HashMap<>();
        //遍历到导入的资源
        importedResources.forEach((resource, readerClass) -> {
            // Default reader selection necessary?
            // 判断reader的类型
            if (BeanDefinitionReader.class == readerClass) {
                if (StringUtils.endsWithIgnoreCase(resource, ".groovy")) {
                    // When clearly asking for Groovy, that's what they'll get...
                    readerClass = GroovyBeanDefinitionReader.class;
                }
                else {
                    // Primarily ".xml" files but for any other extension as well
                    readerClass = XmlBeanDefinitionReader.class;
                }
            }
            // 获取reader
            BeanDefinitionReader reader = readerInstanceCache.get(readerClass);
            if (reader == null) {
                try {
                    // Instantiate the specified BeanDefinitionReader
                    reader = readerClass.getConstructor(BeanDefinitionRegistry.class).newInstance(this.registry);
                    // Delegate the current ResourceLoader to it if possible
                    if (reader instanceof AbstractBeanDefinitionReader) {
                        AbstractBeanDefinitionReader abdr = ((AbstractBeanDefinitionReader) reader);
                        abdr.setResourceLoader(this.resourceLoader);
                        abdr.setEnvironment(this.environment);
                    }
                    readerInstanceCache.put(readerClass, reader);
                }
                catch (Throwable ex) {
                    throw new IllegalStateException(
                        "Could not instantiate BeanDefinitionReader class [" + readerClass.getName() + "]");
                }
            }
    
            // TODO SPR-6310: qualify relative path locations as done in AbstractContextLoader.modifyLocations
            // 加载并注册,这里走从资源加载BeanDefinition流程,即ClassPathXmlApplicationContext 走的那个流程
            reader.loadBeanDefinitions(resource);
        });
    }
    
    • 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
    2.1.4.4、处理ImportBeanDefinitionRegistrar
    2.1.4.4.1、获取importBeanDefinitionRegistrars
    //由上面的 processImports 处理ImportBeanDefinitionRegistrar 实现类时添加,@EnableAutoConfigration 中导入该实现类
    private final Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> importBeanDefinitionRegistrars = new LinkedHashMap<>();
    //org.springframework.context.annotation.ConfigurationClass#getImportBeanDefinitionRegistrars
    public Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> getImportBeanDefinitionRegistrars() {
    	return this.importBeanDefinitionRegistrars;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    2.1.4.4.2、执行ImportBeanDefinitionRegistrar
    //org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsFromRegistrars
    private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
        //遍历
        registrars.forEach((registrar, metadata) ->
                           registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    //org.springframework.context.annotation.ImportBeanDefinitionRegistrar#registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry, org.springframework.beans.factory.support.BeanNameGenerator)
    default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
    	//注册
        registerBeanDefinitions(importingClassMetadata, registry);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这里会调org.springframework.boot.autoconfigure.AutoConfigurationPackages.Registrar#registerBeanDefinitions,这个AutoConfigurationPackages.Registrar是@EnableAutoConfigration导入类,会注册一些 package。

    这里也会被上面的方法调用,注册 EnableConfigurationProperties 导入的类。

  • 相关阅读:
    Python+大数据-Spark技术栈(四) SparkSQL
    彩虹之眼文化集团整体方案设计
    瑞吉外卖项目开发文档2——缓存、读写分离优化
    太阳能发电与蓄电池研究(Matlab代码实现)
    一款跨时代的高性能 Java 框架,启动速度快到飞起
    K8s复习笔记9--war包部署Jenkins war包k8s部署
    字符串函数
    【Java】Collection接口&迭代器
    prtorch.数据的导入与导出
    Git语句
  • 原文地址:https://blog.csdn.net/xuwenjingrenca/article/details/126574407