Spring Boot顶层接口实现类注入项目的方法
1、背景
在项目中,我们通常会具有同一特性的业务类定义一个顶层接口,让业务类实现这个接口,通过接口规范来管理这些类。我们将这些实现接口的业务类交托给Spring容器接口后,有时候需要根据业务类型来选择动态选择对应的业务类阿里处理业务。这个时候就获取到这些业务类并进行管理,在需要时取出对应的业务类处理业务。如何管理就是本期要介绍的内容。
以下是我定义的一个简单的顶层接口,它有两个方法,一个是提供类型的getType()方法,一个是处理业务的hanlde()方法。我们的任务就是对其实现类进行管理,当需要时可根据类型获取对应实现类。
public interface IBaseHandler {/*** 获取处理器类型* @return 处理器类型*/int getType();/*** 处理业务* @param t 业务数据* @param <T> 业务数据类型*/<T> void handler(T t);
}
2、简单的管理方法
我们可以通过使用@Autowired注解将所有实现了IBaseHandler接口的类注入到项目当中,并在需要时遍历业务类对象,获取对应的对象来处理业务。代码如下所示:
@Autowiredprivate List<IBaseHandler> handlers;/*** 处理业务* @param type 业务类型* @param data 业务数据* @param <T> 业务数据类型*/public <T> void handle(int type, T data) {handlers.stream().filter(handler -> handler.getType() == type).findAny().orElseThrow(() -> {// 获取不到业务类对象时打印日志并抛出异常log.error("Failed to get handler, type:{}", type);throw new NoSuchElementException("No such handler");}).handler(data);}
3、更好的管理方法
1、简单管理方法的弊端
上面的简单管理方法用起来方便,但是有两个弊端:
(1)耦合度高,所有需要使用该接口的地方都需要进行注入再遍历的过程。
(2)性能较差,每次执行业务之前都需要遍历一次列表。
2、解决
我们可以使用一个工具类,提供静态方法来获取业务类。这样所有需要获取业务类的地方,就都可以通过该工具类一步获取到所需的业务类。代码如下:
1、工具类代码
@Slf4j
public class HandlerManager {/*** 按照type映射的处理器map*/private static Map<Integer, IBaseHandler> typeHandlerMap = new HashMap<>();/*** 按照类型映射的处理器map*/private static Map<Class<IBaseHandler>, IBaseHandler> clazzHandlerMap = new HashMap<>();/*** 初始化方法,项目启动时调用该方法来初始化map* @param applicationContext spring 上下文对象*/public static void init(ApplicationContext applicationContext) {List<IBaseHandler> handlers = new ArrayList<>();applicationContext.getBeansOfType(IBaseHandler.class).forEach((name, obj) -> handlers.add(obj));// 为了方便,两次循环构建map,一次循环也可以解决,不过人为定义的handler数量不多,一次循环性能提升不大typeHandlerMap = handlers.stream().collect(Collectors.toMap(IBaseHandler::getType, obj -> obj));clazzHandlerMap = handlers.stream().collect(Collectors.toMap(obj -> (Class<IBaseHandler>) obj.getClass(), obj -> obj));}public IBaseHandler getHandlerByType(int type) {return Optional.ofNullable(typeHandlerMap.get(type)).orElseThrow(() -> {// 获取不到处理器打印日志并抛出异常log.info("Failed to get handler, type:{}", type);throw new NoSuchElementException("No such handler error");});}public IBaseHandler getHandlerByClass(Class<IBaseHandler> clazz) {return Optional.ofNullable(clazzHandlerMap.get(clazz)).orElseThrow(() -> {// 获取不到处理器打印日志并抛出异常log.info("Failed to get handler, clazz:{}", clazz);throw new NoSuchElementException("No such handler error");});}}
2、调用工具类的init方法
由于工具类提供的是静态方法,因此无法通过注入的方式来获取到所有的IBaseHanlder,所以需要借助其他可注入IBaseHanlder的类来初始化管理对象,以下是方法:
/*** 项目初始化类* 继承ApplicationContextAware,实现setApplicationContext,可获取ApplicationContext来获取上下文*/
@Component
public class ApplicationInit implements ApplicationContextAware {@Autowiredprivate List<IBaseHandler> handlers;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {// 调用处理器工具类初始化方法HandlerManager.init(applicationContext);}
}
相关文章:
Spring Boot顶层接口实现类注入项目的方法
1、背景 在项目中,我们通常会具有同一特性的业务类定义一个顶层接口,让业务类实现这个接口,通过接口规范来管理这些类。我们将这些实现接口的业务类交托给Spring容器接口后,有时候需要根据业务类型来选择动态选择对应的业务类阿里…...
JDBC介绍-AI问答(通义千问)
一、JDBC介绍 介绍JDBC JDBC(Java Database Connectivity)是Java中用于连接和操作关系型数据库的标准API(应用程序编程接口)。它是由Sun Microsystems(现在是Oracle的一部分)开发,并随Java Deve…...
Spring AI探索
Spring AI概述 该Spring AI项目旨在简化包含人工智能功能的应用程序的开发,避免不必要的复杂性。 该项目从著名的 Python 项目(例如 LangChain 和 LlamaIndex)中汲取灵感,但 Spring AI 并非这些项目的直接移植。该项目的成立基于…...
【代码随想录算法训练Day39】LeetCode 62.不同路径、LeetCode 63.不同路径II
Day39 动态规划第二天 LeetCode 62.不同路径 二维dp数组的含义:走到位置为(i,j)的格子的走法为dp[i][j]种。 递推公式:dp[i][j]dp[i-1][j]dp[i][j-1]。 初始化:dp[i][0]和dp[0][j]都赋值为1. 递归顺序:从左往右,从上…...
浙大版PTA Python程序设计 题目与知识点整理(综合版)
目录 第一章 一、高级语言程序的执行方式 二、变量赋值与内存地址 三、字符编码 3.1 Unicode 3.2 ASCII(American Standard Code for Information Interchange) 四、编程语言分类按照编程范式分类 4.1 面向过程语言 4.2 面向对象语言 五、原码…...
HTML表单深度解析:构建互动的网页界面
表单是HTML中用于收集用户输入信息的重要元素,是网页与用户交互的关键组件。以下是一个典型的HTML表单示例,我们将会详细解析其中的各个元素及属性含义。 <form action"https://xx.xxx.xx/search" target"_self" method"ge…...
git 分支管理规范
分支命名 master 分支 master 为主分支,也是用于部署生产环境的分支,需要确保master分支稳定性。master 分支一般由 release 以及 hotfix 分支合并,任何时间都不能直接修改代码。 develop 分支 develop 为开发环境分支,始终保持…...
Spring Cloud Gateway 详解:构建高效的API网关解决方案
Spring Cloud Gateway 详解:构建高效的API网关解决方案 Spring Cloud Gateway 是 Spring Cloud 生态系统中用于构建 API 网关的核心组件。它基于 Spring WebFlux 构建,旨在提供简单且有效的方式来路由和增强 API 请求。以下是 Spring Cloud Gateway 的详…...
基于Quartus Prime18.1的安装与FPGA的基础仿真教程
Quartus是一种美国科技公司Intel(英特尔)公司开发的FPGA(现场可编辑门阵列)设计编译软件,用作设计、仿真、综合和布局、支持多种编程语言,包括VHDL、Verilog等,并具有丰富的功能和工具库&#x…...
AJAX 和 XML:现代 Web 开发的关键技术
AJAX 和 XML:现代 Web 开发的关键技术 引言 在当今的 Web 开发领域,AJAX 和 XML 是两项至关重要的技术。AJAX(Asynchronous JavaScript and XML)允许网页在不重新加载整个页面的情况下,与服务器交换数据和更新部分网页内容。而 XML(eXtensible Markup Language)则是一…...
vue实现图片预览
在 Vue 中实现图片预览功能,通常涉及监听文件输入的变化,并在用户选择文件后,使用 FileReader API 来读取文件内容,然后显示这个内容作为图片的预览。以下是一个简单的 Vue 组件示例,它实现了图片预览功能:…...
C语言入门系列:流程控制
一,C代码执行顺序 默认情况下,C语言程序从main()函数开始执行,随后按源代码中语句出现的顺序逐一执行。 这意味着,如果不考虑任何控制结构,程序会自上而下,逐行执行每条语句,直到遇到函数调用…...
【深度学习】NLP,Transformer讲解,代码实战
文章目录 1. 前言2. Transformer结构训练过程1. 输入嵌入和位置编码2. 编码器层2.1 单头的注意力机制(便于理解)2.2 多头的注意力机制(Transformer真实使用的)2.3 残差连接和层归一化2.4 前馈神经网络(FFN)2.5 残差连接和层归一化2.6 总结 3. 解码器层 推…...
ES6 .entries用法
.entries() 返回数组的可迭代对象itarator,可以通过for of 来遍历数组或对象的值。但是它们的写法不一样。 数组用法 obj [apple,bananer,orange] for(let [i,v] of obj.entries()){console.log(i)console.log(v) } //输出 // 0 // apple // 1 // bananer // 2 //orange对象…...
【LeetCode 动态规划】买卖股票的最佳时机问题合集
文章目录 1. 买卖股票的最佳时机含冷冻期 1. 买卖股票的最佳时机含冷冻期 题目链接🔗 🍎题目思路: 🍎题目代码: class Solution { public:int maxProfit(vector<int>& prices) {int n prices.size();ve…...
python学习:语法(2)
目录 对象的布尔值 分支结构 双分支结构 多分支结构 嵌套if的使用 条件表达式 Pass语句 range()函数的使用 流程控制语句 对象的布尔值 Python一切皆对象,所有对象都有一个布尔值,通过内置函数bool()获取对象的布尔值 这些…...
经典电源电路基础(变压-整流-滤波-稳压)
1.电源电路的功能和组成 电子电路中的电源一般是低压直流电,先把220v交流电变换成低压直流电,再用整流电路变成脉动的直流电,最后用滤波电路滤除掉脉动直流中的交流成分后才能得到直流电。有的电子设备对电源的质量要求很高,所以…...
生成式人工智能备案办理指南,深度解析大模型备案全流程
早在2023年年初,国家互联网信息办公室、工业和信息化部、公安部针对深度合成服务制定的《互联网信息服务深度合成管理规定》(“《深度合成管理规定》”)顺利施行,其明确了深度合成服务相关方的义务与主体责任,强化了对…...
1527. 患某种疾病的患者
1527. 患某种疾病的患者 题目链接:1527. 患某种疾病的患者 代码如下: # Write your MySQL query statement below select patient_id,patient_name,conditions from Patients where conditions like "DIAB1%" or conditions like "% DI…...
【C/C++】【学生成绩管理系统】深度剖析
可接各类C/C管理系统课设 目录 实现功能 部分1:系统设置和主菜单 1. 引入头文件 2. 定义结构体 3. 函数声明 4. 主函数 部分2:添加学生信息 部分3:删除学生信息 部分4:修改学生信息 部分5:查询学生信息 部分…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!
本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...
MySQL的pymysql操作
本章是MySQL的最后一章,MySQL到此完结,下一站Hadoop!!! 这章很简单,完整代码在最后,详细讲解之前python课程里面也有,感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...
