如何在禁用Bean覆盖时重写Spring Boot的RequestMappingHandlerMapping?
解决Spring Boot中自定义RequestMappingHandlerMapping的Bean冲突问题
首先得明确为啥会触发这个报错:你通过继承DelegatingWebMvcConfiguration并重写requestMappingHandlerMapping()注册Bean的方式,和Spring Boot自动配置里WebMvcAutoConfiguration.EnableWebMvcConfiguration注册的同名Bean产生了冲突,而默认情况下Spring Boot不允许Bean定义覆盖,所以就抛出了这个异常。
其实不用开启allow-bean-definition-overriding来“掩盖”问题,Spring MVC早就给我们留了更优雅的扩展路径——实现WebMvcRegistrations接口,这个接口就是专门用来替换Spring MVC核心组件的,完全不会触发Bean冲突。
具体实现步骤:
- 实现
WebMvcRegistrations接口,重写getRequestMappingHandlerMapping()方法返回你的自定义Handler Mapping:
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import org.springframework.web.servlet.config.annotation.WebMvcRegistrations; public class CustomWebMvcRegistrations implements WebMvcRegistrations { @Override public RequestMappingHandlerMapping getRequestMappingHandlerMapping() { return new MyNewVersionRequestMappingHandlerMapping(); } }
- 在你的配置类里把这个实现类注册为Bean:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MyConfig { @Bean public WebMvcRegistrations customWebMvcRegistrations() { return new CustomWebMvcRegistrations(); } }
- 顺便修正你自定义
RequestMappingHandlerMapping里的小错误(之前getCustomMethodCondition里误用了不属于该方法的handlerType参数):
public class MyNewVersionRequestMappingHandlerMapping extends RequestMappingHandlerMapping { @Override protected RequestCondition<?> getCustomTypeCondition(final Class<?> handlerType) { return new SomeCustomTypeCondition(handlerType); } @Override protected RequestCondition<?> getCustomMethodCondition(final Method method) { // 这里应该基于method参数创建对应的自定义Condition return new SomeCustomMethodCondition(method); } }
为什么这个方法可行?
Spring Boot的WebMvcAutoConfiguration.EnableWebMvcConfiguration在创建RequestMappingHandlerMapping时,会优先检查容器中是否存在WebMvcRegistrations类型的Bean。如果存在,就会调用它的getRequestMappingHandlerMapping()方法获取实例,而不是使用默认实现。这样既完成了组件替换,又不会产生重复Bean的问题,完美避开了需要开启覆盖配置的需求。
内容的提问来源于stack exchange,提问作者Yu Jiaao
相关产品推荐
相关产品推荐

