工厂+策略模式之最佳实践(疾病报卡维护模块API设计)

目录

💻业务场景

🔧应用技术

⚙概要流程

❗开发注意

服务类上标注了 自定义注解 却无法直接利用getDeclaredAnnotation 获取

*Spring代理机制

代理机制的工作原理

代理的工作机制

代理的使用场景

已获取EmrXXXServiceImpl 的Class,如何获取public class EmrXXXServiceImpl extends ServiceImpl implements EmrXXXService 泛型类型:EmrXXX,>


💻业务场景

        某医院急诊系统需要于诊断列表关联相关疾病报卡,并且当诊断提交后,支持医生进行报卡的维护,可与HIS系统端的公卫下疾病报卡管理模块进行联动。
        经调研,考虑各个报卡的新增操作的数据流(各个报卡对应的数据库表不一)有出入,相关业务流一致,则可利用设计模式中的策略+工厂模式,以及泛型、反射、注解等技术实现相关上层API的设计。到达代码简洁,避免硬编码,且更易于扩展和支持更多类型的报卡的目的。

        利用自定义报卡标识注解将每个服务的实例化逻辑封装成不同的策略类;利用仿写Spring Bean工厂的方式,通过依赖注入和组件扫描来自动管理 Bean 的创建和查找,利用符合单一性原则自定义注解,服务类自行声明它们所支持的疾病类型,工厂可动态根据已报卡的服务去初始化报卡服务实例。

🔧应用技术

  • 枚举:报卡相关固化数据的常量(提高代码可读性和可维护性、增强类型安全、简化代码)
  • 泛型:API设计,以此提供更加灵活和通用的接口,实现接口通用。注意泛型擦除机制
  • 反射:灵活获取指定类对象,进行类之父类上的泛型Type的获取等操作
  • 注解:是标识各个报卡服务,支持后续Bean工厂初始化集合存储报卡Service Bean
  • 框架:Spring、Mybatis Plus

⚙概要流程

❗开发注意

服务类上标注了 自定义注解 却无法直接利用getDeclaredAnnotation 获取

已知注解于类的声明处,并且继承链无误(Java 的注解默认不会被继承,除非使用 @Inherited 元注解),注解作用范围为 ElementType.TYPE,并且保留策略是 RetentionPolicy.RUNTIME

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SupportedDiseaseType {String value();
}

最终定位错误为Spring 使用代理机制来管理 Bean,从而导致注解无法直接通过 getDeclaredAnnotation 获取。特别是当使用 CGLIB 代理时,代理类不会继承原始类的注解。

则利用Spring 提供了 AnnotatedElementUtils 工具类,它可以更可靠地获取注解,包括处理代理类的情况。

SupportedDiseaseType annotation = AnnotatedElementUtils.findMergedAnnotation(service.getClass(), SupportedDiseaseType.class);

*Spring代理机制

Spring 使用代理机制来管理 Bean,主要是为了实现 AOP(面向切面编程)和事务管理等功能。Spring 的代理机制允许在不修改原有代码的基础上,动态地为目标对象添加额外的功能,比如日志记录、性能监控、事务管理等。

代理机制的工作原理

Spring 中的代理有两种常见的方式:

1. JDK 动态代理(基于接口):
   - 通过反射机制创建一个实现目标对象接口的代理类,并将代理类与目标对象绑定。
   - 适用于目标类实现了接口的情况。

2. CGLIB 代理(基于子类):
   - 通过继承目标类,动态创建一个目标类的子类,并在该子类中织入增强代码。
   - 适用于目标类没有实现接口的情况,或者目标类没有实现接口但需要增强的情况。

Spring 通过这两种代理方式在运行时动态地生成代理对象,来增强目标对象的行为。代理对象和目标对象的使用是透明的,开发者只需要关注接口或原有类,Spring 会自动为其注入代理功能。

代理的工作机制

- **生成代理对象**:Spring 使用 JDK 动态代理或 CGLIB 代理创建一个代理对象,这个对象通常是目标对象的一个包装。
- **拦截方法调用**:每次调用代理对象的方法时,Spring 会通过代理对象执行相关的增强逻辑,例如日志、事务、权限控制等。
- **目标方法执行**:增强逻辑执行完毕后,代理对象会调用目标对象的实际方法。

代理的使用场景

1. AOP(面向切面编程):
   - 使用 Spring 的 AOP 可以在运行时动态地为对象添加横切关注点(如日志、事务等),而不修改目标对象的源代码。
   
2. 事务管理:
   - Spring 可以通过代理机制来自动管理数据库事务,确保在方法执行过程中根据需要进行事务的开启、提交或回滚。
   
3. 懒加载:
   - 代理对象可以通过懒加载的方式,在实际调用方法时才去创建目标对象,从而提高系统性能。

已获取EmrXXXServiceImpl 的Class,如何获取public class EmrXXXServiceImpl extends ServiceImpl<EmrXXXMapper, EmrXXX> implements EmrXXXService 泛型类型:EmrXXX

直接上代码!

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;public class Main {public static void main(String[] args) {// 假设你已经通过 AOP 得到了 `EmrXXXServiceImpl` 的 Class 对象Class<?> targetClass = EmrXXXServiceImpl.class;// 获取父类的类型参数Type genericSuperclass = targetClass.getGenericSuperclass();// 检查是否是带有泛型的类if (genericSuperclass instanceof ParameterizedType) {ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;// 获取泛型参数类型Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();// 这里假设第一个泛型参数是 `EmrXXXMapper`// 第二个泛型参数是 `EmrXXX`Type secondGenericType = actualTypeArguments[1];// 输出泛型类型的类if (secondGenericType instanceof Class<?>) {Class<?> EmrXXXClass = (Class<?>) secondGenericType;System.out.println("泛型中的 EmrXXX 的类是: " + EmrXXXClass.getName());}}}
}

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

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

相关文章

ARM异常处理 M33

1. ARMv8-M异常类型及其详细解释 ARMv8-M Exception分为两类&#xff1a;预定义系统异常(015)和外部中断(1616N)。 各种异常的状态可以通过Status bit查看&#xff0c;获取更信息的异常原因&#xff1a; CFSR是由UFSR、BFSR和MMFSR组成&#xff1a; 下面列举HFSR、MMFSR、…

【单片机通讯协议】—— 常用的UART/I2C/SPI等通讯协议的基本原理与时序分析

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、通信基本知识1.1 MCU的参见外设1.2 通信的分类按基本的类型从传输方向上来分 二、UART&#xff08;串口通讯&#xff09;2.1 简介2.2 时序图分析2.3 UART的…

Linux axel 下载加速命令详解

简介 axel 命令是一个轻量级、快速且用户友好的 Linux 命令行下载加速器。它通过将文件分割成片段并同时下载来加快下载速度&#xff0c;这对于大文件和网络不好时尤其有用。 axel 支持 HTTP、HTTPS、FTP 和 FTPS 协议。 安装 Debian/Ubuntu sudo apt update sudo apt ins…

Adversarial Machine Learning(对抗机器学习)

之前把机器学习&#xff08;Machine Learning&#xff09;的安全问题简单记录了一下&#xff0c;这里有深入研究了一些具体的概念&#xff0c;这里记录一下方便以后查阅。 Adversarial Machine Learning&#xff08;对抗机器学习&#xff09; Adversarial Examples 相关内容Eva…

STM32 高级 谈一下IPV4/默认网关/子网掩码/DNS服务器/MAC

首先可以通过 winr->输入cmd->输入ipconfig 命令可以查看计算机的各种地址 IPV4&#xff1a;是互联网协议第 4 版&#xff08;Internet Protocol version 4&#xff09;所使用的地址。它是一个 32 位的二进制数字&#xff0c;通常被分为 4 个 8 位的部分&#xff…

安卓音频之dumpsys audio

目录 概述 详述 dumpsys audio 1、音频服务生命周期的事件日志 2、音频焦点事件日志 3、音频流音量信息 4、音量组和设备的相关信息 5、铃声模式 6、音频路由 7、其他状态信息 8、播放活动监控信息 9、录音活动记录 10、AudioDeviceBroker 的记录 11、音效&#…

Linux 更改Jenkins使用其他账户启动

Linux 更改Jenkins使用其他账户启动 步骤一&#xff1a;修改 Jenkins 配置文件1. 编辑 Jenkins 的 systemd 服务文件&#xff1a;2. 在编辑器中添加以下内容&#xff1a;3. 保存并退出编辑器 步骤二&#xff1a;更改 Jenkins 目录的权限步骤三&#xff1a;重新加载 systemd 配置…

【LLM】Python 基础语法

Python 作为最佳的机器学习和深度学习语言&#xff0c;如果你想入门大模型&#xff08;如 GPT、BERT 等&#xff09;与自然语言处理&#xff08;NLP&#xff09;&#xff0c;那么 Python 一定是最佳选择&#xff0c;这篇文章将带你入门Python语法。&#xff08;PS&#xff1a;爆…

【Go】context标准库

文章目录 1. 概述1.1 什么是 Context1.2 设计原理1.3 使用场景1.4 Context 分类核心:Context接口2. 源码解读4个实现emptyCtxTODO 和 BackgroundcancelCtxWithCancelcancelCtx.propagateCancel 构建父子关联parentCancelCtx 获取父上下文中的内嵌cancelCtxcanceltimerCtxWithT…

面试小札:Java后端闪电五连鞭_11

1. 接口和抽象类的区别 - 定义方式&#xff1a; - 接口使用 interface 关键字定义&#xff0c;所有方法默认是 public 和 abstract 的&#xff0c;不能有方法体。例如&#xff1a; interface MyInterface { void method1(); int method2(); } - 抽象类使用 abstract …

【面经】25届 双非本科 字节跳动 北京 四年的总结

点击“硬核王同学”&#xff0c;选择“关注” 福利干货第一时间送达 大家好&#xff0c;我是硬核王同学&#xff0c;最近在做免费的嵌入式知识分享&#xff0c;帮助对嵌入式感兴趣的同学学习嵌入式、做项目、找工作&#xff01; 给大家分享一个25届本科大佬的面经&#xff0c…

select2 下拉框回显问题 树形菜单 部门结构的

版本&#xff1a;Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md 原项目用jsp bootstrap 测试了快一天 终于在kimi上找到结果了 原来的select2 不支持层级结构的回显 需要改成数组的不带层级的方式给到select2 才能正常选择回显 另外需要自已…

解决 vue3 中 echarts图表在el-dialog中显示问题

原因&#xff1a; 第一次点开不显示图表&#xff0c;第二次点开虽然显示图表&#xff0c;但是图表挤在一起&#xff0c;页面检查发现宽高只有100px,但是明明已经设置样式宽高100% 这可能是由于 el-dialog 还没有完全渲染完成&#xff0c;而你的 echarts 组件已经开始尝试渲染图…

计算机网络习题( 第3章 物理层 第4章 数据链路层 )

第3章 物理层 一、单选题 1、下列选项中&#xff0c;不属于物理层接口规范定义范畴的是&#xff08; &#xff09;。 A、 接口形状 B、 引脚功能 C、 传输媒体 D、 信号电平 正确答案&#xff1a; C 2、在物理层接口特性中&#xff0c;用于描述完成每种功能的事件发…

Unity SpriteAtlasManager.atlasRequested趟坑

坑1 场景一加载&#xff0c;unity就触发了SpriteAtlasManager.atlasRequested&#xff0c;如果这时候没有设置SpriteAtlasManager.atlasRequested回调&#xff0c;就会触发这个告警&#xff1a; SpriteAtlasManager.atlasRequested wasnt listened to 解决这个很简单&…

通俗易懂!使用Excel和TF实现Transformer

本文旨在通过最通俗易懂的过程来详解Transformer的每个步骤&#xff01; 假设我们在做一个从中文翻译到英文的过程&#xff0c;我们的词表很简单如下&#xff1a; 中文词表&#xff1a;[机、器、学、习] 英文词表[deep、machine、learning、chinese] 先来看一下Transformer的…

智慧楼盘二维、三维组件融合 720三维全景可视化

本系统通过数字孪生技术&#xff0c;实现小区楼盘系统的可视化展示&#xff0c;整合楼盘内各个系统的数据源&#xff0c;将楼盘模型与房间模型、720三维全景图相结合&#xff0c;实现了从楼盘周边到室内布局的全方位展示&#xff0c;为购房者提供全方位的可视化信息。 整个项目…

adb无法连接到安卓设备【解决方案】报错:adb server version (40) doesn‘t match this client (41);

下载老版本Platformtools​​​​​​​​​​​​​​https://dl.google.com/android/repository/platform-tools_r28.0.2-windows.zip?hlzh-cn 替换原来的platform-tools文件夹即可。 问题原因分析&#xff1a;电脑端adb client版本&#xff08;41&#xff09;和安卓端adb …

QT QCombox QSS样式问题

/*combobox 样式*/ QComboBox#FileterComboBox,QComboBox#DateRangeComboBox{background-color: #262626; /* 背景颜色 */color: #e0e0e0; /* 文本颜色 */border-radius:16px;font-family: "Microsoft YaHei"; /* 文本字体族 */font-size: 18px; /* 文…

Unittest02|TestSuite、TestRunner、HTMLTestRunner、处理excel表数据、邮件接收测试结果

目录 八、测试套件TestSuite和测试运行器TestRunner 1、基本概念 2、创建和使用测试套件 3、 自动发现测试用例、创建测试套件、运行测试 4、生成html的测试报告&#xff1a;HTMLTestRunner 1️⃣导入HTMLTestRunner模块 2️⃣运行测试用例并生成html文件 九、unittest…