You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot升级至2.2.0.RELEASE后启动失败、Bean未加载问题排查

问题根因

该故障由Spring Boot 2.2.0默认集成的Spring Framework 5.2 配置类解析逻辑变更触发,核心触发逻辑如下:

  • 自定义配置类EKMSClientSdkConfiguration继承了来自第三方Jar的抽象类ClientConfiguration,该父类未标注任何Spring配置注解,且内部定义了@Bean方法,其中restClient()直接调用了同类的apiClient()方法
  • Spring 5.2之前,@Configuration默认的Full代理模式(proxyBeanMethods = true)会自动为这类无注解的抽象父类生成CGLIB代理,正确处理类内部@Bean方法的调用逻辑,配置类可以正常注册。5.2版本新增了配置类合法性校验:如果配置类的父类是未标注Spring配置注解的抽象类,框架无法为其生成符合要求的CGLIB代理,会直接跳过整个配置类的解析流程,类上的@ComponentScan、条件注解、类内的@Bean方法、@PostConstruct生命周期方法全部不会生效,直接出现安全提供者未注册、关联Bean未创建、启动失败的现象。
排查步骤
  • 启动应用时在配置文件中添加debug=true,查看配置类评估报告,会看到EKMSClientSdkConfiguration被标记为跳过状态,跳过原因多为配置类无法生成代理子类
  • 查看启动日志的WARN级别日志,会看到5.2版本新增的配置类代理风险提示,明确指向抽象父类的@Bean方法无法被正确拦截
  • 临时将@Configuration注解修改为@Configuration(proxyBeanMethods = false)切换为Lite配置模式重启,如果配置类可以正常加载,即可确认根因判断正确。
解决方案

按改造成本和长期稳定性从高到低选择:

  1. 推荐方案:移除对第三方抽象配置类的继承
    不需要依赖第三方的抽象类结构,直接把父类中定义的restClient()、apiClient()两个@Bean方法复制到自定义配置类中,删除继承关系,从根源上规避代理逻辑兼容问题,后续升级Spring版本也不会出现同类问题。改造后的配置类示例:
    @Configuration
    @Slf4j
    @ComponentScan(basePackages = "com.xxx.yyy.ekms.sdk")
    @ConditionalOnProperty(name = "ekms.enabled", havingValue = "true")
    public class EKMSClientSdkConfiguration
    {
        @PostConstruct
        public void addSecurityProvider()
        {
            Security.addProvider(new BouncyCastleFipsProvider());
        }
    
        @Bean
        public ApiClientBuilder apiClientBuilder()
        {
            return new DefaultApiClientBuilder();
        }
    
        @Bean
        public EKMSClient restClient() {
            return new EKMSRestClientImpl(this.apiClient());
        }
    
        @Bean
        public ApiClient apiClient() {
            return Configuration.getDefaultApiClient();
        }
    }
    
  2. 快速兼容方案:关闭配置类的Bean方法代理
    如果暂时不想调整代码结构,直接在自定义配置类的@Configuration注解中添加proxyBeanMethods = false参数,切换为Lite配置模式。该模式下Spring不会为配置类生成CGLIB代理,自然不会触发抽象父类的代理校验逻辑,配置类可以正常加载。

    注意:Lite模式下类内部@Bean方法互相调用不会走Spring容器的Bean获取逻辑,会直接执行本地方法。当前场景中apiClient()方法本身是直接返回静态默认客户端实例,没有依赖其他Spring Bean的逻辑,所以不会出现Bean重复创建或者依赖注入失败的问题。
    注解修改示例:

    @Configuration(proxyBeanMethods = false)
    @Slf4j
    @ComponentScan(basePackages = "com.xxx.yyy.ekms.sdk")
    @ConditionalOnProperty(name = "ekms.enabled", havingValue = "true")
    public class EKMSClientSdkConfiguration extends ClientConfiguration
    {
        // 原有业务代码无需修改
    }
    
  3. 兜底方案:显式注册核心Bean
    如果以上两种方案都不适用,可以直接在启动类或者其他通用配置类中通过@Bean方法显式注册BouncyCastleFipsProvider、ApiClient、EKMSClient等核心Bean,绕过配置类扫描解析的流程,不过这种方式维护成本较高,只建议临时应急使用。

内容的提问来源于stack exchange,提问作者Amrita Sah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 18:42:33