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

Spring Boot集成Keycloak出现RequestMappingHandlerAdapter循环引用如何解决

问题根因

你的CommonPredicateConfiguration本身属于Spring Web MVC配置体系的实现类,会参与RequestMappingHandlerAdapter的初始化流程。你在配置类中直接注入RequestMappingHandlerAdapter,同时Keycloak安全配置的初始化又依赖MVC核心组件,三者形成了互相等待初始化的循环依赖链路。

解决方案

方案1:添加@Lazy懒加载注解(改造成本最低)

直接在注入RequestMappingHandlerAdapter的位置添加@Lazy注解,Spring会注入代理对象而非直接触发Bean初始化,等@PostConstruct执行时RequestMappingHandlerAdapter已经完成初始化,不会触发循环依赖。
修改后的CommonPredicateConfiguration代码如下:

@Configuration
public class CommonPredicateConfiguration implements WebMvcConfigurer {

    private RequestMappingHandlerAdapter adapter;

    @Autowired
    public void setAdapter(@Lazy RequestMappingHandlerAdapter adapter) {
        this.adapter = adapter;
    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new CommonPredicateResolver());
    }

    @PostConstruct
    public void prioritizeCommonPredicateMethodHandler() {
        List<HandlerMethodArgumentResolver> argumentResolvers =
                new ArrayList<>(adapter.getArgumentResolvers());
        // 移除Querydsl自带的解析器逻辑不变
        argumentResolvers.removeIf(resolver -> resolver instanceof QuerydslPredicateArgumentResolver);
        adapter.setArgumentResolvers(argumentResolvers);
    }
}

这个方案不需要改动原有逻辑,完全保留配置类的职责拆分。

方案2:实现BeanPostProcessor(更规范的初始化后修改方案)

将修改RequestMappingHandlerAdapter参数解析器的逻辑从@PostConstruct迁移到Bean后置处理器中,完全避开MVC配置初始化的循环链路:

@Configuration
public class CommonPredicateConfiguration implements WebMvcConfigurer, BeanPostProcessor {

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new CommonPredicateResolver());
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof RequestMappingHandlerAdapter adapter) {
            List<HandlerMethodArgumentResolver> argumentResolvers =
                    new ArrayList<>(adapter.getArgumentResolvers());
            argumentResolvers.removeIf(resolver -> resolver instanceof QuerydslPredicateArgumentResolver);
            adapter.setArgumentResolvers(argumentResolvers);
        }
        return bean;
    }
}

这个方案不需要注入RequestMappingHandlerAdapter,从根本上消除了循环依赖的触发点,是更符合Spring扩展规范的实现方式。

不推荐的临时方案

如果需要快速验证,可以在application.properties中添加配置开启循环引用允许:

spring.main.allow-circular-references=true

该方案只是绕过了循环依赖校验,没有解决根本问题,不建议在生产环境使用。

内容的提问来源于stack exchange,提问作者Fatih Bulut

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 23:15:03