springboot项目启动异常 - required a single bean, but 2 were found,发现Service和其实现类均被注入到Spring容器

今天遇到一个问题,启动报错,报错如下:

 排查了Service注入的使用的方式没有什么问题,也没有多个实现类:

Controller的注入也没有问题: 

当然按照编译器给出的提示,给实现类增加 @Primary 注解也是可以解决的,但这始终不是问题的根本的原因。

后来通过调试源码,发现居然是注解@MapperScan的问题:

@SpringBootApplication
@Slf4j
@MapperScan("cn.edu.ncwu.pv_dev.*")
@EnableCaching
public class PvDevApplication {

    public static void main(String[] args) {
        SpringApplication.run(PvDevApplication.class, args);
    }

}

代码模块目录结构如下: 

因为@MapperScan的范围为整个包下面了,@MapperScan作用:指定要变成实现类的接口所在的包,然后包下面的所有接口在编译之后都会生成相应的实现类(或者说@MapperScan 配置一个或多个包路径,自动的扫描这些包路径下的类,自动的为它们生成代理类)。所以导致service对应的实现类都被扫描生成一个Bean对象,即使已经用@Service注解也会再生成一个Bean对象。

Class<? extends Annotation> annotationClass() default Annotation.class;

后来代码调整为扫描指定的Mapper目录:

@MapperScan("cn.edu.ncwu.pv_dev.*.domain.*.factory.repository")

也可以调整为:

@MapperScan(value = {"cn.edu.ncwu.pv_dev.*"}, annotationClass = Mapper.class)

即可解决。

总结:

为什么出现required a single bean, but 2 were found错误?

1、Mybatis扫描@MapperScan中指定包下的接口,生成接口的实现类,注入到Spring容器。

2、Spring框架扫描到我编写的接口实现类,注入Spring容器,因此就有了两个bean。

解决办法:

1、在springboot项目中建议直接在Mapper接口上添加@Mapper,不要使用@MapperScan。

2、若要使用@MapperScan注解,注意配置好扫描的范围,避免重复扫描注入spring bean导致出现上述问题。


版权声明:本文为xiyafei122原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。