spring接口多实现类,选择性注入的4种解决方案
2022/8/25 4:23:00
本文主要是介绍spring接口多实现类,选择性注入的4种解决方案,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
一、问题的描述
在实际的系统应用开发中我经常会遇到这样的一类需求,相信大家在工作中也会经常遇到:
-
同一个系统在多个省份部署。
-
一个业务在北京是一种实现方式,是基于北京用户的需求。
-
同样的业务在上海是另外一种实现方式,与北京的实现方式大同小异
遇到这样的需求,我们通常会定义一个业务实现的接口,比如:
public interface IDemoService { public void doSomething(); }
在北京环境下这样实现,比如:
@Component public class DemoServiceBeijing implements IDemoService { @Override public void doSomething() {System.out.println("北京的业务实现");} }
在上海环境下这样实现,比如:
@Component public class DemoServiceShanghai implements IDemoService { @Override public void doSomething() {System.out.println("上海的业务实现");} }
然后我们写一个模拟业务测试用例
@SpringBootTest class DemoApplicationTests { //这里注入的demoService是DemoServiceShanghai,还是DemoServiceBeijing? @Resource IDemoService demoService; @Test void testDemoService() { demoService.doSomething(); } }
当我们执行这个测试用例的时候一定会报错,因为Spring发现了两个IDemoService的实现类。它不知道去实例化哪一个实现类,来作为IDemoService的实际业务处理bean。当然我们期望的状态是:
-
在北京部署系统的时候,使用DemoServiceBeijing作为IDemoService的实现类完成依赖注入
-
在上海部署系统的时候,使用DemoServiceShanghai作为IDemoService的实现类完成依赖注入
二、相对低级解决方案
面对上面的需求,先说几个相对低级的解决方案,这几个方案虽然可以实现我们期望的状态,但是对运维不够友好。
2.1. 方案一:使用@Primary
注解
假如在北京部署系统的时候,在DemoServiceBeijing的类上面加上@Primary
,该注解的作用就是强迫从多个实现类里面选一个实现类,如果Spring不知道选哪一个,我们告诉它一个默认的。
@Primary @Component public class DemoServiceBeijing implements IDemoService {
2.2. 方案二:使用@Resource
注解
因为Resource注解默认使用名称进行依赖注入,所以变量名明确叫做demoServiceBeijing(首字母小写),使用的就是DemoServiceBeijing实现类。
@Resource IDemoService demoServiceBeijing; //这里的变量名称指定了bean名称 //IDemoService demoService; 被替换掉
或者
@Resource(name = "demoServiceBeijing") //使用resource注解明确指定名称 IDemoService demoService;
2.3.方案三:使用@Qualifier
注解
与上文同样的道理,使用@Qualifier
注解,指定bean的名称进行依赖注入
@Qualifier("demoServiceBeijing") //使用Qualifier注解明确指定名称 @Resource IDemoService demoService;
上面所提到的三个方案虽然都可以解决:在不同的部署环境下使用不同的接口实现类完成依赖注入的问题。但是这样不好,因为一旦我们要把部署环境从beijing(北京)换成shanghai(上海),就需要把上面的注解的位置或者内容全都修改一遍(所有的实现类代码都要修改)。
三、相对高级的解决方案
我们提出进一步的期望:就是只修改一个配置就能完成部署环境切换的操作。比如:
deploy: province: beijing
当我们期望把部署环境从北京切换到上海的时候,只需要将上文配置中的beijing 改成 shanghai ,这该怎么实现呢?
- 在北京的实现类上面加上ConditionalOnProperty注解,havingValue的值为beijing
@Component @ConditionalOnProperty(value="deploy.province",havingValue = "beijing") public class DemoServiceBeijing implements IDemoService {
- 在上海的实现类上面加上ConditionalOnProperty注解,havingValue的值为shanghai
@Component @ConditionalOnProperty(value="deploy.province",havingValue = "shanghai") public class DemoServiceShanghai implements IDemoService {
「ConditionalOnProperty注解在这里的作用就是」:读取配置文件发现deploy.province
,并将该配置的值与havingValue匹配,匹配上哪一个就实例化哪一个类作为该接口的实现类bean注入到Spring容器中(当然注入过程需要配合@Component
注解实现)。
这篇关于spring接口多实现类,选择性注入的4种解决方案的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-15JavaMailSender是什么,怎么使用?-icode9专业技术文章分享
- 2024-11-15JWT 用户校验学习:从入门到实践
- 2024-11-15Nest学习:新手入门全面指南
- 2024-11-15RestfulAPI学习:新手入门指南
- 2024-11-15Server Component学习:入门教程与实践指南
- 2024-11-15动态路由入门:新手必读指南
- 2024-11-15JWT 用户校验入门:轻松掌握JWT认证基础
- 2024-11-15Nest后端开发入门指南
- 2024-11-15Nest后端开发入门教程
- 2024-11-15RestfulAPI入门:新手快速上手指南