• Boot 中bean配置覆盖


    问题:

          项目引用第三方jar包,需要对@Configuration配置类中的某个bean进行覆盖。服务启动过程遇到了bean已被注册异常、新加的bean不加载的问题。

     举例:

     第三方jar包MybatisPlusConfig 类

    @Configuration
    public class MybatisPlusConfig {
        @Bean
        public MybatisPlusInterceptor innerInterceptor() {
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
            //分页
            interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
            //乐观锁
            interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
            interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(this.tenantLineHandler()));
            interceptor.addInnerInterceptor(new SystemLineInnerInterceptor(this.systemLineHandler()));
            return interceptor;
        }

    }

    当前项目MybatisPrimaryConfig 类

    public class MybatisPrimaryConfig {
    
        @Bean
        public MybatisPlusInterceptor innerInterceptor() {
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
            //分页
            interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
            //乐观锁
            interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
            interceptor.addInnerInterceptor(new SystemLineInnerInterceptor(this.systemLineHandler()));
            return interceptor;
        }

    }

     1.思路是MybatisPrimaryConfig类的方法bean名字innerInterceptor覆盖MybatisPlusConfig类的方法bean名字innerInterceptor

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

     3. bean加载顺序
    配置allowBeanDefinitionOverriding为true后,却出现新配置不注册的问题。@SpringBootApplication的属性scanBasePackages数组,注册bean时,是按数组顺序注册的。把引用包的包名写在项目包名前面,项目中的配置类才可覆盖掉引用包的bean。@SpringBootApplication(scanBasePackages={"com.qm.qfc.common.entity.config","com.qm.qfc.dpf.dpfservice"})

    1. 1.spring中的org.springframework.context.annotation.ComponentScanAnnotationParser包扫描代码
    2. public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
    3. ....
    4. Set<String> basePackages = new LinkedHashSet();
    5. String[] basePackagesArray = componentScan.getStringArray("basePackages");
    6. String[] var19 = basePackagesArray;
    7. int var21 = basePackagesArray.length;
    8. int var22;
    9. for(var22 = 0; var22 < var21; ++var22) {
    10. String pkg = var19[var22];
    11. String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg), ",; \t\n");
    12. Collections.addAll(basePackages, tokenized);
    13. }
    14. Class[] var20 = componentScan.getClassArray("basePackageClasses");
    15. var21 = var20.length;
    16. for(var22 = 0; var22 < var21; ++var22) {
    17. Class<?> clazz = var20[var22];
    18. basePackages.add(ClassUtils.getPackageName(clazz));
    19. }
    20. if (basePackages.isEmpty()) {
    21. basePackages.add(ClassUtils.getPackageName(declaringClass));
    22. }
    23. scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
    24. protected boolean matchClassName(String className) {
    25. return declaringClass.equals(className);
    26. }
    27. });
    28. return scanner.doScan(StringUtils.toStringArray(basePackages));
    29. }
    30. 2.在方法1中查看doScan方法是在org.springframework.context.annotation.ClassPathBeanDefinitionScanner
    31. protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    32. Assert.notEmpty(basePackages, "At least one base package must be specified");
    33. Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
    34. //依次对basePackages中配置的类进行注入
    35. for (String basePackage : basePackages) {
    36. Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
    37. ...
    38. }
    39. return beanDefinitions;
    40. }

  • 相关阅读:
    js中创建对象的5种方法
    SpringMVC深解--一起学习吧之架构
    八月 NFT 行业解读:数据下滑,熊市持续
    奇瑞新能源小蚂蚁,一款实用好看的居家小车
    多年锤炼,迈向Kata 3.0 !走进开箱即用的安全容器体验之旅
    使用TensorRT-LLM进行高性能推理
    不安全的HTTP方法
    tensorflow自定义激活函数(带有条件判断)
    二叉搜索树
    在 360 度绩效评估中应该问的 20 个问题
  • 原文地址:https://blog.csdn.net/lvhui321/article/details/125490612