首页 技术 正文
技术 2022年11月14日
0 收藏 410 点赞 3,089 浏览 4019 个字

  出现问题的项目算是一个新项目,但基本的脚手架代码是从另一个项目里迁过来的,原项目并没有报错,只有新项目才报异常。看报错内容,判断发生冲突的主要是spring-boot-starter-security和springfox-swagger2这两个jar包的文件。

  新项目错误如下:

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
15:22:32.350 spotcheck-system [main] ERROR o.s.b.d.LoggingFailureAnalysisReporter - ***************************
APPLICATION FAILED TO START
***************************Description:Method springSecurityFilterChain in org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration required a single bean, but 2 were found:
- requestMappingHandlerMapping: defined by method 'requestMappingHandlerMapping' in class path resource [org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.class]
- swagger2ControllerMapping: defined by method 'swagger2ControllerMapping' in class path resource [springfox/documentation/swagger2/configuration/Swagger2DocumentationConfiguration.class]Action:Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumedorg.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping' available: expected single matching bean but found 2: requestMappingHandlerMapping,swagger2ControllerMapping

  我的项目中出错代码是这一行,在原项目并没有报错。

Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = applicationContext.getBean(RequestMappingHandlerMapping.class).getHandlerMethods();

  getBean方法默认是byType来加载bean对象的,如果取到相同类型的2个就会报错。我分别查看了错误中提示的DelegatingWebMvcConfiguration.class和Swagger2DocumentationConfiguration.class。

  1. DelegatingWebMvcConfiguration.class里并没有requestMappingHandlerMapping方法,DelegatingWebMvcConfiguration继承了WebMvcConfigurationSupport.class类,在WebMvcConfigurationSupport.class类中有requestMappingHandlerMapping方法,返回值是RequestMappingHandlerMapping.class。代码如下:

    /**
* Return a {@link RequestMappingHandlerMapping} ordered at 0 for mapping
* requests to annotated controllers.
*/
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
......
}

  2. Swagger2DocumentationConfiguration.class里有swagger2ControllerMapping方法如下:

  @Bean
public HandlerMapping swagger2ControllerMapping(
Environment environment,
DocumentationCache documentationCache,
ServiceModelToSwagger2Mapper mapper,
JsonSerializer jsonSerializer) {
return new PropertySourcedRequestMappingHandlerMapping(environment, new Swagger2Controller(environment, documentationCache, mapper, jsonSerializer));
}

  这个方法里的返回值类型PropertySourcedRequestMappingHandlerMapping继承了RequestMappingHandlerMapping类,

public class PropertySourcedRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
......
}

  所以可能Spring加载时,根据byType形式会认错了吧。

  解决办法:既然Spring加载时使用byType形式会报错,那我们就用byName形式加载。Spring中使用@Bean声明的方法,如果没有指定名称,默认的name就是方法名。所以我们把出错代码改成:

        RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping) applicationContext.getBean("requestMappingHandlerMapping");
Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods();

  到此问题解决。

补充一下:

  假设自己项目中有一个接口,同时有两个实现类,并且实现类都使用了@Service注解,你在使用过程中使用了@Autowired注解进行引用。这时Spring初始化时就会报错:expected single matching bean but found 2 ,因为@Autowired默认是byType形式加载的。

  解决办法就是用@Primary、@Qualifier这两个注解来解决问题。

  @Primary注解是用来声明2个实现类那个是主要的。与@Component、@Service等注解放到一起使用。这时Spring通过@Autowired加载时,就会判断一下, 优先使用@Primary注解的类。

  @Qualifier显示声明加载类的名称,与@Autowired放到一起使用,这样Spring加载时判断类型相同,会在通过名称筛选出需要的类,就不会报错了。其实@Autowired + @Qualifier = @Resource,如果真需要byName形式加载,直接使用@Resource就可以了。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,492
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,907
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,740
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,495
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,132
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,295