• springboot bean覆盖注册的问题(allowBeanDefinitionOverriding配置)


    springboot bean覆盖注册的问题-allowBeanDefinitionOverriding配置
    问题描述
    问题分析
    1. allowBeanDefinitionOverriding配置
    2. bean加载顺序
    问题描述
    项目引用三方jar包,需要对@Configuration配置类中的某个bean进行重写。过程中遇到了bean已被注册异常、以及新加的bean不加载的问题。

    问题分析
    测试项目中的问题时,写了两个config,都注册了RestTemplate

    DefaultConfig

    package top.macondo;
    @Configuration
    public class DefaultConfig {
        @Bean
        public RestTemplate getRestTemplate() {
            System.out.println("default bean");
            return new RestTemplate();
        }
    }


    NewConfig

    package com.example;
    @Configuration
    public class NewConfig {
        @Bean
        public RestTemplate getRestTemplate(){
            System.out.println("new bean");
            return new RestTemplate();
        }
    }


    1. allowBeanDefinitionOverriding配置
    在默认情况下,启动服务后,会报bean已被注册异常。

    The bean 'getRestTemplate', defined in class path resource [top/macondo/DefaultConfig.class], could not be registered. A bean with that name has already been defined in class path resource [com/example/NewConfig.class] and overriding is disabled.

    springboot中,allowBeanDefinitionOverriding 默认为false;spring默认为true。需要在application.properties中新增spring.main.allow-bean-definition-overriding=true

    参考spring中 allowBeanDefinitionOverriding(spring.main.allow-bean-definition-overriding) 分析

    2. bean加载顺序
    配置allowBeanDefinitionOverriding为true后,却出现新配置不注册的问题。经过对加载流程的进一步排查,发现NewConfig中的RestTemplate被DefaultConfig覆盖。

    @SpringBootApplication的属性scanBasePackages数组,注册bean时,是按数组顺序注册的。把引用包的包名写在项目包名前面,项目中的配置类才可覆盖掉引用包的bean。

    @SpringBootApplication(scanBasePackages = {"top.macondo","com.example"})
    spring中的ComponentScanAnnotationParser包扫描代码
    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Assert.notEmpty(basePackages, "At least one base package must be specified");
        Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
        //依次对basePackages中配置的类进行注入
        for (String basePackage : basePackages) {
            Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
            ...
        }
        return beanDefinitions;
    }
    

      

  • 相关阅读:
    [原创]mac终端前面的计算机名怎么改??
    iOS获取当前设备方向
    mac电脑Coding显示/隐藏文件
    从tomcat7升级到tomcat8的一个坑
    Tomcat环境开发技巧
    No.2 网络功能
    No.1 持久化
    No.0 项目起步
    读mysqlbinlog二三事
    版本号小常识
  • 原文地址:https://www.cnblogs.com/blogtech/p/16090772.html
Copyright © 2020-2023  润新知