java通过反射获取加了某个注解的所有的类
有时候我们会碰到这样的情况:
有n个场景,每个场景都有自己的逻辑,即n个处理逻辑,
这时候我们就需要通过某个参数的值代表这n个场景,然后去加载每个场景不同的bean对象,即不同的类,这些类中都有一个同名的方法,但是里面的逻辑不同,类似策略模式、工厂模式等
假设这样的场景,银行卡分几种类型,比如普通会员,黄金会员,黑卡会员......
普通会员、黄金会员和黑卡的权限不一样,消费能力不一样等等内容,这里我们就以消费的能力举例,普通会员只能转账5万元,黄金只能转账20万元,黑卡100万元,
我们有3各类,分别是Putong.class,Huangjin.class,Heika.class,这三个类里面有一个同样的方法,名字叫:checkPermissions()方法,三个类上都加了一个自定义注解@MemberTypeDefinition
demo
自定义注解
package com.zygxsq.test;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 自定义注解***/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MemberTypeDefinition {/*** 数据源默认执行方法*/public static final String DEFAULT_DAO_METHOD_NAME = "checkPermissions";/*** 数据源执行的方法名称, 默认为getData, 该方法必须只有一个参数{@link BaseDataSpec}, 返回结果必须是{@link BaseResult}, 可见性必须是public** @return 方法名称*/String value() default DEFAULT_DAO_METHOD_NAME;
}
Putong.class
package com.zygxsq.test;import org.springframework.stereotype.Component;/*** 普通会员处理逻辑***/
@MemberTypeDefinition
@Slf4j
@Component
public class Putong {public BaseResult checkPermissions(BaseDataSpec baseDataSpec) {// 省略中间的一些处理逻辑// ......// 省略中间的一些处理逻辑// 最后封装返回结果BaseResult baseResult = new BaseResult();baseResult.setResponse("我是普通会员");return baseResult;}
}
Huangjin.class
package com.zygxsq.test;import org.springframework.stereotype.Component;/*** 黄金会员处理逻辑***/
@MemberTypeDefinition
@Slf4j
@Component
public class Huangjin {public BaseResult checkPermissions(BaseDataSpec baseDataSpec) {// 省略中间的一些处理逻辑// ......// 省略中间的一些处理逻辑// 最后封装返回结果BaseResult baseResult = new BaseResult();baseResult.setResponse("我是黄金会员");return baseResult;}
}
Heika.class
package com.zygxsq.test;import org.springframework.stereotype.Component;/*** 黑卡会员处理逻辑***/
@MemberTypeDefinition
@Slf4j
@Component
public class Heika {public BaseResult checkPermissions(BaseDataSpec baseDataSpec) {// 省略中间的一些处理逻辑// ......// 省略中间的一些处理逻辑// 最后封装返回结果BaseResult baseResult = new BaseResult();baseResult.setResponse("我是黑卡会员");return baseResult;}
}
入参和返回参数对象
入参对象
package com.zygxsq.test;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;import java.io.Serializable;
import java.util.List;/*** 入参数据对象***/
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class BaseDataSpec implements Serializable {/*** serialVersionUID*/private static final long serialVersionUID = -5669150877852962345L;/*** id*/private String id;/*** 名字*/private String name;
}
返回结果对象
package com.zygxsq.test;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;/*** 返回结果对象***/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BaseResult implements Serializable {/*** serialVersionUID*/private static final long serialVersionUID = 7510262928468530569L;private String response;
}
那如何通过反射进行加载呢,BaseDataAnnotationApplication.class
package com.zygxsq.test;import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;/*** 启动加载***/
@Slf4j
@Component
public class BaseDataAnnotationApplication implements ApplicationContextAware, InitializingBean {private ApplicationContext applicationContext;/*** <className,V>*/private final Map<String, Object> loadMap = Maps.newConcurrentMap();/*** 特殊人群表缓存 <id,1> ,获取 SpecialPeople.class里面所有的表名*/public static Map<String,Object> dmTablesMap = Maps.newConcurrentMap();@Overridepublic void afterPropertiesSet() throws Exception {// 获取加了 MemberTypeDefinition 注解的源表beanloadSourceDefinition();// 获取SpecialPeople.class里面所有的表名loadSpecialMap();}private void loadSourceDefinition() throws Exception{Map<String, Object> beans = applicationContext.getBeansWithAnnotation(MemberTypeDefinition.class);for (final Object serviceObject : beans.values()) {final Class<? extends Object> calcuteClass = serviceObject.getClass();MemberTypeDefinition annotation = calcuteClass.getAnnotation(MemberTypeDefinition.class);if (null == annotation) {log.error("类: {} 注解缺失", calcuteClass);continue;}loadMap.put(calcuteClass.getName(), serviceObject);}}/*** 获取SpecialPeople.class里面所有的表名* @throws Exception*/private void loadSpecialMap() throws Exception {dmTablesMap = Maps.newConcurrentMap();Field[] declaredFields = SpecialPeople.class.getDeclaredFields();for (Field declaredField : declaredFields) {Class<?> type = declaredField.getType();String typeName = declaredField.getGenericType().getTypeName();Class<?> aClass = Class.forName(typeName);if (type == People.class) {People people = (People) declaredField.get(aClass);String id = people.getId().trim();dmTablesMap.put(id, "1");}}}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}public <T> BaseResult buildData(Class<T> clazz, BaseDataSpec baseDataSpec) throws Exception{// 获取执行方法名, 默认为getDataString methodName;MemberTypeDefinition annotation = clazz.getAnnotation(MemberTypeDefinition.class);if (annotation == null || StringUtils.isBlank(annotation.value())) {methodName = MemberTypeDefinition.DEFAULT_DAO_METHOD_NAME;} else {methodName = annotation.value();}Method method;Object bean = loadMap.get(clazz.getName());BaseResult result = null;try {method = bean.getClass().getMethod(methodName, BaseDataSpec.class);result = (BaseResult) method.invoke(bean, baseDataSpec);} catch (NoSuchMethodException e) {throw new Exception(clazz.getName()+"未找到执行方法:"+methodName);} catch (Exception e2) {throw new Exception(clazz.getName()+"未找到执行方法:"+methodName);}return result;}public <T> BaseResult buildData(Class<?> sourceClass) {return null;}
}
通过上面的application,就可以加对象加载到缓存里了,如何我们直接调用即可
相关文章:
java通过反射获取加了某个注解的所有的类
有时候我们会碰到这样的情况:有n个场景,每个场景都有自己的逻辑,即n个处理逻辑,这时候我们就需要通过某个参数的值代表这n个场景,然后去加载每个场景不同的bean对象,即不同的类,这些类中都有一个…...
Warshall算法
🚀write in front🚀 📜所属专栏:> 算法 🛰️博客主页:睿睿的博客主页 🛰️代码仓库:🎉VS2022_C语言仓库 🎡您的点赞、关注、收藏、评论,是对我…...
vector中迭代器失效的问题及解决办法
目录 vector常用接口 vector 迭代器失效问题 vector中深浅拷贝问题 vector的数据安排以及操作方式,与array非常相似。两者的唯一差别在于空间的运用的灵活性。array 是静态空间,一旦配置了就不能改变;要换个大(或小) 一点的房子&#x…...
【蓝桥杯刷题训练营】day05
1 数的分解 拆分成3个数相加得到该数 然后采用了一种巨愚蠢的办法: int main() {int count 0;int a 2;int b 0;int c 1;int d 9;int a1, a2, a3;int c1, c2, c3;int d1, d2, d3;for (a1 0; a1 < 2; a1){for (a2 0; a2 < 2; a2){for (a3 0; a3 <…...
线程中断interrupt导致sleep产生的InterruptedException异常
强制当前正在执行的线程休眠(暂停执行),以“减慢线程”。 Thread.sleep(long millis)和Thread.sleep(long millis, int nanos)静态方法当线程睡眠时,它睡在某个地方,在苏醒之前不会返回到可运行状态。 当睡眠时间到期…...
ubuntu的快速安装与配置
文章目录前言一、快速安装二 、基础配置1 Sudo免密码2 ubuntu20.04 pip更新源3 安装和配置oneapi(infort/mpi/mkl) apt下载第一次下载的要建立apt源apt下载(infort/mpi/mkl)4 安装一些依赖库等5 卸载WSLpython总结前言 win11系统 ubuntu20.04 提示:以下…...
人工智能AI工具汇总(AIGC ChatGPT时代个体崛起)
NameCategoryWebsiteDescription描述《AIGC时代:超级个体的崛起》小报童https://xiaobot.net/p/SuperIndividual 介绍AIGC,ChatGPT,使用技巧与搞钱方式。Masterpiece Studio3Dhttps://masterpiecestudio.comSimplifying 3D Creation with AI…...
【rust-grpc-proxy】在k8s中,自动注入代理到pod中,再不必为grpc调试而烦恼
目录前言原理sidecarwebhook实现安装k8s设置webhook使用尾语前言 rust-grpc-proxy 目前功能基本完善。是时候上环境开始应用了。 之前考虑是gateway模式或者sidecar模式。 思考良久之后,觉得两种模式都有使用场景,那就都支持。本次就带来sidecar模式的食…...
VisualStudio2022制作多项目模板及Vsix插件
一、安装工作负载 在vs2022上安装“visual studio扩展开发 ”工作负载 二、制作多项目模板 导出项目模板这个我就不再多说了(项目→导出模板→选择项目模板,选择要导出的项目→填写模板信息→完成)。 1.准备模板文件 将解决方案中的多个…...
仿写简单IOC
目录 TestController类: UserService类: 核心代码SpringIOC: Autowired和Component注解 SpringIOCTest 类 编辑 总结: TestController类: Component public class TestController {Autowiredprivate UserService userService;public void test…...
liunx下安装node exporter
1 建立文件夹 cd /opt mkdir software 下载最新的包,并解压 https://prometheus.io/download/ 下载 curl -LO https://github.com/prometheus/node_exporter/releases/download/v0.18.1/node_exporter-0.18.1.linux-amd64.tar.gz 3.解压 tar -xvf node_exporter-0.…...
lambda函数
Lambda(函数指针)lambda 是c11非常重要也是最常用的特性之一,他有以下优点:可以就地匿名定义目标函数或函数对象,不需要额外写一个函数lambda表达式是一个匿名的内联函数lambda表达式定义了一个匿名函数,语法如下:[cap…...
【Python入门第二十七天】Python 日期
Python 日期 Python 中的日期不是其自身的数据类型,但是我们可以导入名为 datetime 的模块,把日期视作日期对象进行处理。 实例 导入 datetime 模块并显示当前日期: import datetimex datetime.datetime.now() print(x)运行实例 2023-0…...
C++基础知识【5】数组和指针
目录 一、概述 数组 指针 二、数组 2.1、数组的声明 2.2、数组的初始化 2.3、数组的访问 2.4、多维数组 2.5、数组作为函数参数 三、指针 3.1、指针的声明 3.2、指针的赋值 3.3、指针的访问 3.4、指针运算 3.5、指针数组和数组指针 3.6、二级指针 四、数组和指…...
Vim使用操作命令笔记
Vim使用操作命令笔记在普通模式下,输入 : help tutor 就可以进入vim的教学 在 terminal 中输入 vim 文件名 就可以打开文件 vim有两种模式 normal mode (普通模式)→ 指令操作 insert mode (输入模式&…...
【论文阅读】Robust Multi-Instance Learning with Stable Instances
1、摘要与引言 以往的MIL算法遵循i.i.d假设:训练样本与测试样本都分别来自于同一分布中,而这一假设往往与现实应用中有所出入。研究人员通过计算训练样本与测试样本之间的密度比对训练样本进行加权,以解决分布变化带来的问题。 分布的变化发…...
洛谷 P5116 [USACO18DEC]Mixing Milk B
题目链接:P5116 [USACO18DEC]Mixing Milk B - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题目描述 农业,尤其是生产牛奶,是一个竞争激烈的行业。Farmer John 发现如果他不在牛奶生产工艺上有所创新,他的乳制品生意可能就会受…...
华为OD机试 - 最左侧冗余覆盖子串(C 语言解题)【独家】
最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧文章目录 使用说明本期题目:最左侧冗…...
实验7 图像水印
本次实验大部分素材来源于山大王成优老师的讲义以及冈萨雷斯(MATLAB版),仅作个人学习笔记使用,禁止用作商业目的。 文章目录一、实验目的二、实验例题1. 数字图像水印技术2. 可见水印的嵌入3. 不可见脆弱水印4. 不可见鲁棒水印一、…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
深入理解Optional:处理空指针异常
1. 使用Optional处理可能为空的集合 在Java开发中,集合判空是一个常见但容易出错的场景。传统方式虽然可行,但存在一些潜在问题: // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...
HTML前端开发:JavaScript 获取元素方法详解
作为前端开发者,高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法,分为两大系列: 一、getElementBy... 系列 传统方法,直接通过 DOM 接口访问,返回动态集合(元素变化会实时更新)。…...
[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG
TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码:HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...
ui框架-文件列表展示
ui框架-文件列表展示 介绍 UI框架的文件列表展示组件,可以展示文件夹,支持列表展示和图标展示模式。组件提供了丰富的功能和可配置选项,适用于文件管理、文件上传等场景。 功能特性 支持列表模式和网格模式的切换展示支持文件和文件夹的层…...
Spring AOP代理对象生成原理
代理对象生成的关键类是【AnnotationAwareAspectJAutoProxyCreator】,这个类继承了【BeanPostProcessor】是一个后置处理器 在bean对象生命周期中初始化时执行【org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization】方法时…...
