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. 不可见鲁棒水印一、…...

docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...

ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险
C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...

边缘计算网关提升水产养殖尾水处理的远程运维效率
一、项目背景 随着水产养殖行业的快速发展,养殖尾水的处理成为了一个亟待解决的环保问题。传统的尾水处理方式不仅效率低下,而且难以实现精准监控和管理。为了提升尾水处理的效果和效率,同时降低人力成本,某大型水产养殖企业决定…...
2025.6.9总结(利与弊)
凡事都有两面性。在大厂上班也不例外。今天找开发定位问题,从一个接口人不断溯源到另一个 接口人。有时候,不知道是谁的责任填。将工作内容分的很细,每个人负责其中的一小块。我清楚的意识到,自己就是个可以随时替换的螺丝钉&…...