springboot/maven复合项目出现Field service in controller required a single bean, but 2 were found

时间:2025-03-20 07:21:38

1、问题背景(问题已解决

2、===============下面开始讲问题=====================

3、本人也没有对这个问题停止过脚步,也经过了如下几个分析过程:

4、解决方法


【问题背景】--问题已解决

背景:整合公司基础框架时出现的这个问题,想让这个文档成为这种问题的终结者。

先说一下问题,这个问题可能有人遇到过:

Field service in BaseController required a single bean, but 2 were found:
    - DicServiceImpl: defined in file []
    - TestServiceImpl: defined in file []

初步分析为项目加载时出现了注入冲突,也就是无法通过ByType和ByName获得唯一的Bean

在BaseController中注入的service出现了重复情况,在下文中可以看到两个实现类都继承了BaseController,所以都注入了service这个Bean。但我上一个项目如法炮制却没有出现在这样的问题,泛型失效了?

===============下面开始讲问题=====================

项目架构是Springboot,JDK 1.8.0.191,泛型,maven复合项目结构,的配置有必要介绍下:

@EnableConfigurationProperties
@EnableTransactionManagement
@SpringBootApplication
@ComponentScan({"A","B","C","D"})    // 确定A、B、C、D包-包含了下文中所有的代码
public class Application extends SpringBootServletInitializer{


    public static void main(String[] args) {
        SpringApplication app = new SpringApplication();
        (args);
    }
}

下面的代码块是基础架构的去除了业务代码的一部分,,以便于各位了解问题的大致情况

@Controller
public class TestController extends BaseController<TestServiceImpl, TestMapper, Test>{
}
@Controller
public class DicController extends BaseController<DicServiceImpl, DicMapper, Dic> {
}

// ==上面controller对应的父类
public abstract class BaseController <S extends BaseServiceImpl<D,T>, D extends BaseMapper<T>, T extends BasePojo<T>> {
    @Autowired
    protected S service;
}

@Service
public class TestServiceImpl extends BaseServiceImpl<TestMapper, Test> implements TestService {
}
@Service
public class DicServiceImpl extends BaseServiceImpl<DicMapper, Dic> implements DicService{
}

// ==上面service对应的父类
public abstract class BaseServiceImpl<D extends BaseMapper<T>, 
                                                        T extends BasePojo<T>> {
    @Autowired
    protected D mapper;
}

public interface TestMapper extends BaseMapper<Test>{
}
public interface DicMapper extends BaseMapper<Dic>{
}

// ==上面的mapper对应的父类
public interface BaseMapper<T> {
}



我没有对这个问题停止过脚步,大概回忆起如下几个分析过程

1、通过console的提示给实现类加上了@Primary(不推荐),或者在@Autowired自动注入的地方加上了@Qualifier指定,

问题虽然得到了解决,但是根据我上一个项目的经验,并没有在项目中使用这些注解依然能够正常运行,唯一的不同就是上个项目没分模块package,而且不区分service的父类和实现类,这就是为什么要追究问题的原因。

2、排除了中的包扫描配置未扫描到的问题

3、在spring获取上下文的地方打印出了所有的Bean,没有发现有重名的Bean

4、在@Service旁,指定Bean的name->@Service(testServiceOnly),无效。

到目前为止还是存在这样的疑惑,这么好的框架不应该让我每个都加注解才能不冲突吧!

5、既然所有依据控制台的解决方案都无效,我开始根据朋友们的意见检查项目,最后找到了解决方法。

下面是控制台加载整个项目的日志,和控制台循环输出的上下文中的bean:

20:32:41.803 [main] INFO   - Starting Application on tujiawei with PID 20288 (*\classes started by 10985 in jgzl-web)
20:32:41.822 [main] DEBUG  - Running with Spring Boot v2.1., Spring v5.1.
20:32:41.822 [main] INFO   - The following profiles are active: dev
20:32:45.422 [main] INFO  $BeanPostProcessorChecker - Bean '' of type [$$EnhancerBySpringCGLIB$$18a5e7ad] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
20:32:46.315 [main] INFO   - Tomcat initialized with port(s): 8080 (http)
20:32:46.352 [main] INFO  .http11.Http11NioProtocol - Initializing ProtocolHandler ["http-nio-0.0.0.0-8080"]
20:32:46.367 [main] INFO   - Starting service [Tomcat]
20:32:46.368 [main] INFO   - Starting Servlet engine: [Apache Tomcat/9.0.16]
20:32:46.391 [main] INFO   - The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the : [D:\jre1.8_191\bin;]
20:32:46.668 [main] INFO  .[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext
20:32:46.668 [main] INFO   - Root WebApplicationContext: initialization completed in 4704 ms
20:32:46.867 [main] INFO   - ===========================设置@34d4860f, started on Thu Jul 18 20:32:41 CST 2019
ApplicationContext ac = ();
String[] names = ();
for (String name : names) {
    (">>>>>>" + name);
}
("------\nBean 总计:" + ());


result:
>>>>>>localeCharsetMappingsCustomizer
>>>>>>
>>>>>>multipartConfigElement
>>>>>>multipartResolver
等300+个bean
------
Bean 总计: 354

解决方法:

检查所有继承了BaseController的类,看是否指定了泛型,如果没有指定泛型,那么这些类将会被注入同一个beantype

而BaseController中的@Autowired,将无法通过byType获取唯一的bean。所以导致此问题的产生。

==这种自动注入的原理是来自Spring4.0的新特性——泛型依赖注入==