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
相关产品推荐
相关产品推荐

