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

news2025/2/7 23:07:46

目录

💻业务场景

🔧应用技术

⚙概要流程

❗开发注意

服务类上标注了 自定义注解 却无法直接利用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.coloradmin.cn/o/2267192.html

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

相关文章

帧缓存的分配

帧缓存实际上就是一块内存。在 Android 系统中分配与回收帧缓存&#xff0c;使用的是一个叫 ION 的内核模块&#xff0c;App 使用 ioctl 系统调用后&#xff0c;会在内核内存中分配一块符合要求的内存&#xff0c;用户态会拿到一个 fd&#xff08;有的地方也称之为 handle&…

StarRocks元数据无法合并

一、先说结论 如果您的StarRocks版本在3.1.4及以下&#xff0c;并且使用了metadata_journal_skip_bad_journal_ids来跳过某个异常的journal&#xff0c;结果之后就出现了FE的元数据无法进行Checkpoint的现象&#xff0c;那么选择升级版本到3.1.4以上&#xff0c;就可以解决。 …

图像处理-Ch2-空间域的图像增强

Ch2 空间域的图像增强 文章目录 Ch2 空间域的图像增强Background灰度变换函数(Gray-level Transformation)对数变换(Logarithmic)幂律变换(Power-Law)分段线性变换函数(Piecewise-Linear)对比度拉伸(Contrast-Stretching)灰度级分层(Gray-level Slicing) 直方图处理(Histogram …

c# 2024/12/27 周五

6《详解类型、变量与对象》36 详解类型、变量与对象 _1_哔哩哔哩_bilibili

云手机+Facebook:让科技与娱乐完美结合

移动互联网时代&#xff0c;Facebook作为全球最大的社交媒体平台之一&#xff0c;早已成为企业、品牌和组织竞相角逐的营销阵地。而云手机的出现&#xff0c;则为Facebook营销注入了新的活力&#xff0c;其独特的优势让营销活动更加高效、精准且灵活。本文将深入探讨云手机在Fa…

【蓝桥杯——物联网设计与开发】拓展模块4 - 脉冲模块

目录 一、脉冲模块 &#xff08;1&#xff09;资源介绍 &#x1f505;原理图 &#x1f505;采集原理 &#xff08;2&#xff09;STM32CubeMX 软件配置 &#xff08;3&#xff09;代码编写 &#xff08;4&#xff09;实验现象 二、脉冲模块接口函数封装 三、踩坑日记 &a…

【再谈设计模式】享元模式~对象共享的优化妙手

一、引言 在软件开发过程中&#xff0c;我们常常面临着创建大量细粒度对象的情况&#xff0c;这可能会导致内存占用过高、性能下降等问题。享元模式&#xff08;Flyweight Pattern&#xff09;就像是一位空间管理大师&#xff0c;它能够在不影响功能的前提下&#xff0c;有效地…

Unity 读Excel,读取xlsx文件解决方案

Unity读取表格数据 效果&#xff1a; 思路&#xff1a; Unity可以解析Json&#xff0c;但是读取Excel需要插件的帮助&#xff0c;那就把这个功能分离开&#xff0c;读表插件就只管读表转Json&#xff0c;Unity就只管Json解析&#xff0c;中间需要一个存储空间&#xff0c;使用…

WebRTC服务质量(11)- Pacer机制(03) IntervalBudget

WebRTC服务质量&#xff08;01&#xff09;- Qos概述 WebRTC服务质量&#xff08;02&#xff09;- RTP协议 WebRTC服务质量&#xff08;03&#xff09;- RTCP协议 WebRTC服务质量&#xff08;04&#xff09;- 重传机制&#xff08;01) RTX NACK概述 WebRTC服务质量&#xff08;…

STM32完全学习——FATFS0.15移植SD卡

一、下载FATFS源码 大家都知道使用CubMAX可以很快的将&#xff0c;FATFS文件管理系统移植到单片机上&#xff0c;但是别的芯片没有这么好用的工具&#xff0c;就需要自己从官网下载源码进行移植。我们首先解决SD卡的驱动问题&#xff0c;然后再移植FATFS文件管理系统。 二、SD…

Ollama+OpenWebUI+llama3本地部署

引言 llama3在4月19日刚刚发布&#xff0c;官方的对比结果中在开源模型中堪称世界第一&#xff0c;整好周六日有时间&#xff0c;在魔搭社区上测试一下 2 安装Ollama 2.1 下载Ollama 登录Ollama官网下载Ollama安装包 GitHub&#xff1a;https://github.com/ollama/ollama?t…

新品:SA628F39大功率全双工音频传输模块

SA628F39是一款高集成度的8W大功率全双工无线数据语音一体通话模块&#xff0c;专为高效、稳定的远程通信设计。该模块内置高速微控制器、高性能射频芯片、功率放大器、ESD静电保护和硬件看门狗芯片&#xff0c;具备反接保护、过流过压保护和防死机保护等多重安全功能&#xff…

Unity EasyAR入门教程

文章目录 Easy不用下载盗版安装SDK注册应用ID最简单的识别注意点 Easy不用下载盗版 EasyAR可以免费试用&#xff0c;如果不在乎水印&#xff0c;直接去官网下载即可 EasyAR官网 安装SDK 先下载&#xff0c;官网找到下载页&#xff0c;如下选择 下载后不是普通的unityPackag…

ID卡网络读卡器Python小程序开发

UDP网络读卡器Python示例代码。 主页UI设计界面&#xff1a; UI代码&#xff1a; from PyQt5 import QtCore, QtGui, QtWidgetsclass Ui_Frame(object):def setupUi(self, Frame):Frame.setObjectName("Frame")Frame.resize(1082, 685)font QtGui.QFont()font.set…

yarn list --pattern vuex-module-decorators

dgqdgqdeMac-mini spid-admin % yarn list --pattern vuex-module-decorators yarn list v1.22.22 └─ vuex-module-decorators0.16.1 ✨ Done in 0.24s.好的&#xff0c;这段代码是一个典型的 Vuex 模块定义&#xff0c;使用了 vuex-module-decorators 库。这个库为 Vuex 提…

微机接口课设——基于Proteus和8086的打地鼠设计(8255、8253、8259)Proteus中Unknown 1-byte opcode / Unknown 2-byte opcode错误

原理图设计 汇编代码 ; I/O 端口地址定义 IOY0 EQU 0600H IOY1 EQU 0640H IOY2 EQU 0680HMY8255_A EQU IOY000H*2 ; 8255 A 口端口地址 MY8255_B EQU IOY001H*2 ; 8255 B 口端口地址 MY8255_C EQU IOY002H*2 ; 8255 C 口端口地址 MY8255_MODE EQU IOY003H*2 ; …

【HENU】河南大学计院2024 计算机网络 期末复习知识点

和光同尘_我的个人主页 一直游到海水变蓝。 计网复习 第一章互联网组成类别交换方式分组交换的要点&#xff1a;分组交换的优点&#xff1a; 网络性能指标体系结构网络协议五层协议 第二章&#xff1a;物理层物理层的主要任务&#xff08;四大特性&#xff09;通信的三种方式…

chatwoot 开源客服系统搭建

1. 准备开源客服系统&#xff08;我是用的Chatwoot &#xff09; 可以选择以下开源客服系统作为基础&#xff1a; Chatwoot: 功能强大&#xff0c;支持多渠道客户对接&#xff0c;&#xff08;支持app&#xff0c;web&#xff09;。Zammad: 现代的开源工单系统。FreeScout: 免…

python爬虫----爬取视频实战

python爬虫-爬取视频 本次爬取&#xff0c;还是运用的是requests方法 首先进入此网站中&#xff0c;选取你想要爬取的视频&#xff0c;进入视频页面&#xff0c;按F12&#xff0c;将网络中的名称栏向上拉找到第一个并点击&#xff0c;可以在标头中&#xff0c;找到后续我们想要…

【PPTist】表格功能

前言&#xff1a;这篇文章来探讨一下表格功能是怎么实现的吧&#xff01; 一、插入表格 我们可以看到&#xff0c;鼠标移动到菜单项上出现的提示语是“插入表格” 那么就全局搜索一下&#xff0c;就发现这个菜单在 src/views/Editor/CanvasTool/index.vue 文件中 <Popov…