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的新特性——泛型依赖注入==