springboot接口注入 有多个实现类怎么办,springboot配置注入的几种方式
目录
一.引言二.代码演示1.问题描述2.解决方案2.1使用@自动连线的时候将接口变量名改为实现类的限定名2.2 使用@自动连线配合@限定符指定限定名注入实现类2.3 @ ConditionalOnProperty三.总结
一.引言
我们在使用跳羚进行开发的时候经常用到@Autowired和@Resource进行依赖注入,但是当我们一个接口对应多个不同的实现类的时候如果不进行一下配置项目启动时就会报错,那么怎么根据不同的需求注入不同的类型就是一个值得考虑的问题,虽然@Autowired和@Resource就可以实现,但是我们也可以选择更加灵活的@ConditionalOnProperty注解来实现
二.代码演示
1.问题描述
TestController.java包com。举例。演示。控制器;导入com。举例。演示。服务。testservice导入org。spring框架。豆子。工厂。注释。自动连线;导入org。spring框架。网络。绑定。注释。请求映射;导入org。spring框架。网络。绑定。注释。休息控制器;/* * * * @类名测试控制器* @作者许巍* @ DATE 2022/6/28 */@ rest controller @请求映射( test )公共类TestController { //注入需要的service @ Autowired TestService TestService;@ request mapping( test )public void test(){ testservice。问好();}}TestService.java
包com。举例。演示。服务;/* * * * @ InterfaceName TestService * @作者许巍* @日期2022/6/28 */公共接口TestService { /** * sayHello方法*/void say hello();}测试服务实现类一TestServiceImplOne.java
包com。举例。演示。服务。impl导入com。举例。演示。服务。testservice导入org。slf4j。记录者;导入org。SLF 4j。伐木工厂;/* * * * @类名testserviceimpone * @作者许巍* @日期2022/6/28 */@公共服务类testserviceimpone实现TestService { private static final Logger=Logger factory。获取记录器(testserviceimpone。类);/** *说你好方法*/@覆盖public void say hello(){ logger。信息(我是testserviceimpone’);} }测试服务实现类二TestServiceImplTwo.java
包com。举例。演示。服务。impl导入com。举例。演示。服务。testservice导入org。slf4j。记录者;导入org。SLF 4j。伐木工厂;/* * * * @类名TestServiceImplTwo * @作者许巍* @日期2022/6/28
*/@Servicepublic class TestServiceImplTwo implements TestService { private static final Logger LOGGER = LoggerFactory.getLogger(TestServiceImplTwo.class); /** * sayHello方法 */ @Override public void sayHello() { LOGGER.info("I am TestServiceImplTwo"); }}这时我们的程序启动会报错,大概意思就是找到了两个实现类
***************************APPLICATION FAILED TO START***************************Description:Field testService in com.example.demo.controller.TestController required a single bean, but 2 were found: - testServiceImplOne: defined in file [/Users/xuwei/Desktop/Projects/IdeaProjects/demo/target/classes/com/example/demo/service/impl/TestServiceImplOne.class] - testServiceImplTwo: defined in file [/Users/xuwei/Desktop/Projects/IdeaProjects/demo/target/classes/com/example/demo/service/impl/TestServiceImplTwo.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 consumed
2.解决方案
2.1使用@Autowired的时候将接口变量名改为实现类的限定名
TestController.java修改为如下
package com.example.demo.controller; import com.example.demo.service.TestService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController; /** * @ClassName TestController * @Author xuwei * @DATE 2022/6/28 */@RestController@RequestMapping("test")public class TestController { //修改变量名为实现类的限定名 @Autowired TestService testServiceImplOne; @RequestMapping("test") public void test(){ testServiceImplOne.sayHello(); }}我们可以将接口的命名改为对应实现类的限定名,默认为类名且首字母小写,当然我们也可以自己给接口的实现类配置限定名,例如@Service("serviceOne") 之后在引用时使用我们配置的限定名,这样程序都可以自动找到实现类,测试结果如下:
2.2 使用@Autowired配合@Qualifier指定限定名注入实现类
其实这个方法的原理和上面的很相似,@Autowired会默认根据type进行注入,如果type相同会根据id进行注入,也就是我们说的限定名,我们只需要让它找到对应限定名的类即可,上面我们通过修改接口变量名的方式来实现,同时我们还可以配合@Qualifier注解来实现相同的目的TestController.java修改为如下
package com.example.demo.controller; import com.example.demo.service.TestService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController; /** * @ClassName TestController * @Author xuwei * @DATE 2022/6/28 */@RestController@RequestMapping("test")public class TestController { //配合注解指定限定名 @Qualifier("testServiceImplTwo") @Autowired TestService testService; @RequestMapping("test") public void test(){ testService.sayHello(); }}当然,和上一种方法相同,我们注解中填的值是实现类的限定名,可以使用默认,也可以和上面一样在使用@Service时进行配置,测试结果如下:
2.3@ConditionalOnProperty
以上两种方法都是硬编码方式,在我们需要进行用户配置时很不方便,所以我们可以使用@ConditionalOnProperty注解来实现配置文件控制的功能在TestController中使用@Resource注入
package com.example.demo.controller; import com.example.demo.service.TestService;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; /** * @ClassName TestController * @Author xuwei * @DATE 2022/6/28 */@RestController@RequestMapping("test")public class TestController { //使用@Resource注入 @Resource TestService testService; @RequestMapping("test") public void test(){ testService.sayHello(); }}TestServiceImplOne.java
package com.example.demo.service.impl; import com.example.demo.service.TestService;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;import org.springframework.stereotype.Component; /** * @ClassName TestServiceImplOne * @Author xuwei * @DATE 2022/6/28 */@Component@ConditionalOnProperty(name = "serviceControl",havingValue = "serviceOne")public class TestServiceImplOne implements TestService { private static final Logger LOGGER = LoggerFactory.getLogger(TestServiceImplOne.class); /** * sayHello方法 */ @Override public void sayHello() { LOGGER.info("I am TestServiceImplOne"); }}TestServiceImplTwo.java
package com.example.demo.service.impl; import com.example.demo.service.TestService;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;import org.springframework.stereotype.Component; /** * @ClassName TestServiceImplTwo * @Author xuwei * @DATE 2022/6/28 */@Component@ConditionalOnProperty(name = "serviceControl",havingValue = "serviceTwo")public class TestServiceImplTwo implements TestService { private static final Logger LOGGER = LoggerFactory.getLogger(TestServiceImplTwo.class); /** * sayHello方法 */ @Override public void sayHello() { LOGGER.info("I am TestServiceImplTwo"); }}在配置文件中配置我们使用的类
测试结果如下
三.总结
前两种方法都是去寻找接口的限定名,第三种方法中@ConditionalOnProperty(name = "serviceControl",havingValue = "serviceOne")注解的name属性对应配置文件中的key值,而havingValue属性对应的是配置文件中我们上面定义的name属性对应的value值到此这篇关于SpringBoot根据配置注入接口的不同实现类的文章就介绍到这了,更多相关SpringBoot注入接口实现类内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。