获取接口的所有实现

一、获取接口所有实现类

方法1:JDK自带的ServiceLoader实现
ServiceLoader是JDK自带的一个类加载器,位于java.util包当中,作为 A simple service-provider loading facility。

(1)创建接口

package com.example.demo.service;import java.text.ParseException;public interface UserService{void register() throws ParseException;
}

(2)创建实现类
第一个实现类UserServiceImpl

package com.example.demo.service.impl;import com.example.demo.common.HfiTrace;
import com.example.demo.service.UserService;
import org.springframework.stereotype.Service;@Service
public class UserServiceImpl implements UserService {public UserServiceImpl(UserServiceImpl2 userServiceImpl2) { //由于构造函数先于依赖注入执行,所以这里执行的时候postConstructTest2还没有注入,所以报错userServiceImpl2.register();}@Override@HfiTracepublic void register(){System.out.println("register user");}
}

第二个实现类 UserServiceImpl2

package com.example.demo.service.impl;import com.example.demo.service.UserService;
import org.springframework.stereotype.Service;@Service
public class UserServiceImpl2 implements UserService {@Overridepublic void register(){System.out.println("register user");}
}

第三个实现类 UserServiceImpl3

package com.example.demo.service.impl;import com.example.demo.service.UserService;
import org.springframework.stereotype.Service;@Service
public class UserServiceImpl3 implements UserService {@Overridepublic void register(){System.out.println("register user 3");}
}

(3)在resources目录下添加:META-INF/services/目录,新增一个文件:用你的接口全路径名称命名一个文件(不加后缀),然后在该文件中一行一个添加你的接口实现类的全路径名。
在这里插入图片描述
(4)在第三步新增的文件中,添加接口所有实现类的全路径名,如:
在这里插入图片描述
(5)测试

ServiceLoader<UserService> load = ServiceLoader.load(UserService.class);Iterator<UserService> it = load.iterator();while (it.hasNext()) {UserService service = it.next();service.register();}//for(UserService userService : load){//    userService.register();//}

方法2:使用Spring自带的方法
Application.getBeansOfType();
Spring作为一个容器,管理着一个项目中所有经过配置的Java类(xml配置文件或Annotation方式)。如果某个接口的所有实现类均被Spring托管了,那么通过Spring就可以很简单的返回这些实现类。

@Component
public class userServiceLocator implements ApplicationContextAware {/*** 存储 UserService接口的所有实现类*/private Map<String, UserService> userServiceMap;private List<UserService> userServiceList;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {// 通过上下文,根据接口类型返回相应的所有实现类beanuserServiceMap = applicationContext.getBeansOfType(UserService.class);userServiceList = new ArrayList<>(userServiceMap.values());}/*** 获取所有实现类** @return*/public Map<String, UserService> getAllMap() {return userServiceMap;}/*** 通过名称获取某个实现类** @param beanName*            bean名字* @return*/private UserService getByName(String beanName) {return userServiceMap.get(beanName);}/*** 获取所有实现类** @return*/public List<UserService> getAllList() {return userServiceList;}/*** 根据枚举获取某个实现类** @param xxxTypeEnum* @return*/public UserService get(XxxTypeEnum xxxTypeEnum) {UserService xxxService = userServiceList.stream().filter(s -> s.isSupport(xxxTypeEnum)).collect(Collectors.toList()).get(0);return xxxService;}}

二、策略模式典型应用

spring自动注入接口的多个实现类(结合策略设计模式)
在使用spring开发的时候,有时候会出现一个接口多个实现类的情况,但是有没有有时候有这样一种情况,就是你的逻辑代码里面还不知道你需要使用哪个实现类,就是比如说:你去按摩,按摩店里面有几种会员打折,比如有,vip、svip和普通用户,那按摩店里面是不是需要对这些会员定义好不同的折扣,然后根据每个用户不同的会员计算出不同的消费情况

虽然这样的情况,对于一般人来说,第一眼肯定就是说,直接加 if else 去判断就可以了

这样做,对于实现功能而言,肯定是没问题,如果以后这个按摩店又增加一种会员,那你是不是又要去修改你的逻辑代码去在加一个 if else ,这样就违反了系统架构设计的开闭原则,这样写if else 也使你的代码看起来不优雅。

在代码里面,我们可以先定义一个DiscountStrategy接口类

//顶层会员接口,这个接口的实现类有多个

public interface DiscountStrategy {public String getType();public double disCount(double fee);}

然后在写他的几个实现类

/**
普通用户实现类
*/
@Service
public class NormalDisCountService implements  DiscountStrategy {public String getType(){return "normal";}public double disCount(double fee){return fee * 1;}}
/**
会员实现类
*/
@service
public class VipDisCountService  implements  DiscountStrategy{public String getType(){return "vip";}public double disCount(double fee){return fee * 0.8;}}
/**
svip超级会员实现类
*/
@Service
public class SVipDisCountService  implements  DiscountStrategy {public String getType(){return "svip";}public double disCount(double fee){return fee * 0.5;}}

解决方案
然后当一个用户进来消费的时候,根据你当前的身份去打折扣

定义一个map集合,然后把所有的实现类都放入到这个集合中,然后根据当前的会员类型去进行不同的操作

@Service
public class DisCountStrageService {Map<String,DiscountStrategy> discountStrategyMap = new HashMap<>();// 构造函数,如果你是集合接口对象,那么久会把spring容器中所有关于该接口的子类,全部抓出来放入到集合中@Authwired public DisCountStrageService(List<DiscountStrategy> discountStrategys){for (DiscountStrategy discountStrategy: discountStrategys) {discountStrategyMap.put(discountStrategy.getType(),discountStrategy);}}public double disCount(String type,Double fee){DiscountStrategy discountStrategy =discountStrategyMap.get(type);return discountStrategy.disCount(fee);}
}

测试类

@RunWith(SpringRunner.class)
@SpringBootTest
public class MzySpringModeApplicationTests {@AutowiredOrderService orderService;@AutowiredDisCountStrageService disCountStrageService;@Testpublic void contextLoads() {//orderService.saveOrder();double vipresult = disCountStrageService.disCount("vip",100d);double svipresult = disCountStrageService.disCount("svip",100d);double normalresult = disCountStrageService.disCount("normal",100d);System.out.println(vipresult);System.out.println(svipresult);System.out.println(normalresult);}
}

其实这就是java设计模式的策略模式,只不过就是用构造函数注入到list集合中

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/67093.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数据--难点--地图的制作

地图一直是亮点也是难点&#xff0c;刚刚进公司的时候也很难懂~~做出来的也很难看 纯CSS3使用vw和vh视口单位实现h5页面自适应&#xff0c;gulp自动监听sass改动并保存到css中 当修改了sass里面的代码后&#xff0c;gulp会自动监听修改内容并同名保存到css文件夹中&#xff0…

纯C#使用Visionpro工具2 操作斑点工具

结果图 通过斑点工具中非圆性找取圆特征 代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.For…

计算机设计大赛国赛一等奖项目分享——基于多端融合的化工安全生产监管可视化系统

文章目录 一、计算机设计大赛国赛一等奖二、项目背景三、项目简介四、系统架构五、系统功能结构六、项目特色&#xff08;1&#xff09;多端融合&#xff08;2&#xff09;数据可视化&#xff08;3&#xff09;计算机视觉&#xff08;目标检测&#xff09; 七、系统界面设计&am…

《测试设计思想》——图书推荐

前言&#xff1a; 在当今软件行业飞速发展的时代&#xff0c;软件测试的重要性日益凸显。为了帮助读者提高测试效率和测试质量&#xff0c;清华大学出版社推出了一本名为《测试设计思想》的书籍&#xff0c;由知名专家周海旭老师撰写。这本书深入探讨了测试设计的思想和方法&am…

CentOS查看磁盘IO

CentOS查看磁盘IO 使用iotop命令&#xff08;top命令对应&#xff09; sudo iotop该命令将实时显示磁盘IO活动&#xff0c;按IO使用率排序&#xff0c;并显示每个进程的IO信息。 使用iostat命令&#xff1a; iostat -dx该命令将显示磁盘IO统计信息&#xff0c;包括每个设备…

kubernetes二进制部署2之 CNI 网络组件部署

CNI 网络组件部署 一&#xff1a;K8S提供三大接口1容器运行时接口CRI2云原生网络接口CNI3云原生存储接口CSI 部署 flannelK8S 中 Pod 网络通信&#xff1a;Overlay Network&#xff1a;VXLAN&#xff1a;Flannel:Flannel udp 模式的工作原理&#xff1a;ETCD 之 Flannel 提供说…

Golang下载安装

目录 1. 下载压缩包 2. 解压 3. 查看SDK是否安装成功 4. 配置环境变量 5. 查看环境变量是否配置成功 1. 下载压缩包 官网下载地址&#xff1a; All releases - The Go Programming Language Windows64位选择如下下载&#xff1a; 2. 解压 解压后内容如下&#xff1a; …

浅谈人工智能技术与物联网结合带来的好处

物联网是指通过互联网和各种技术将设备进行连接&#xff0c;实时采集数据、交互信息的网络&#xff0c;对设备实现智能化自动化感知、识别和控制&#xff0c;给人们带来便利。 人工智能是计算机科学的一个分支&#xff0c;旨在研究和开发能够模拟人类智能的技术和方法。人工智能…

迪瑞克斯拉算法 — 优化

在上一篇迪瑞克斯拉算法中将功能实现了出来&#xff0c;完成了图集中从源点出发获取所有可达的点的最短距离的收集。 但在代码中getMinDistanceAndUnSelectNode()方法的实现并不简洁&#xff0c;每次获取minNode时&#xff0c;都需要遍历整个Map&#xff0c;时间复杂度太高。这…

Android T 窗口层级其二 —— 层级结构树的构建(更新中)

如何通过dump中的内容找到对应的代码&#xff1f; 我们dump窗口层级发现会有很多信息&#xff0c;adb shell dumpsys activity containers 这里我们以其中的DefaultTaskDisplayArea为例 在源码的framework目录下查找该字符串&#xff0c;找到对应的代码就可以通过打印堆栈或者…

玩赚音视频开发高阶技术——FFmpeg

随着移动互联网的普及&#xff0c;人们对音视频内容的需求也不断增加。无论是社交媒体平台、电商平台还是在线教育&#xff0c;都离不开音视频的应用。这就为音视频开发人员提供了广阔的就业机会。根据这些年来网站上的音视频开发招聘需求来看&#xff0c;音视频开发人员的需求…

ChatGPT or BingChat

你相信我们对大模型也存在「迷信权威」吗&#xff1f; ChatGPT 的 GPT-4 名声在外&#xff0c;我们就不自觉地更相信它&#xff0c;优先使用它。但我用 ChatALL 比较 AI 大模型们这么久&#xff0c;得到的结论是&#xff1a; ChatGPT GPT-4 在大多数情况下确实是最强&#xf…