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

如何实现大文件断点续传、秒传
大家先来了解一下几个概念: 「文件分块」:将大文件拆分成小文件,将小文件上传\下载,最后再将小文件组装成大文件; 「断点续传」:在文件分块的基础上,将每个小文件采用单独的线程进行上传\下载&…...

备战蓝桥python——完全平方数
完全平方数 链接: 完全平方数 暴力解法: n int(input()) for i in range(1, n1):if(((i*n)**0.5)%10.0):print(i)break运用数论相关知识求解 任意一个正整数都可以被分解成若干个质数乘积的形式,例如 :2022∗5120 \ 2^{2}*5^{1}\,20 22∗51 由此…...

WebRTC中的NAT穿透
NAT简介 我们知道,WebRTC会按照内网、P2P、中转的顺序来尝试连接。在大部分的情况下,实际是使用P2P或者中转的。这里P2P的场景主要使用的技术就是NAT穿透。 我们先简单了解下NAT。NAT在真实网络中是常见的,它的出现一是为了解决ipv4地址不够…...

SpringCloud-高级篇(一)
目录: (1)初识Sentinel-雪崩问题的解决方案 (2)服务保护Sentinel和Hystrix对比 (3)Sentinel初始-安转控制台 (4)整合微服务和Sentinel 微服务高级篇 (1&…...

电脑自动重启是什么原因?详细解说
案例:电脑自动重启是什么原因? “一台用了一年的电脑,最近使用,每天都会一两次莫名其妙自动重启,看了电脑错误日志,看不懂什么意思,一直找不到答案。有没有高手知道怎么解决这个问题的。” 当…...

2023美国大学生数学建模竞赛E题思路
problem 背景: 光污染用于描述过度或不良使用人造光。我们称之为光污染的一些现象包括光侵入、过度照明和光杂波。在大城市,太阳落山后,这些现象最容易在天空中看到:然而,它们也可能发生在更偏远的地区。 光污染会改变我们对夜空…...

蓝桥杯三月刷题 第五天
文章目录💥前言😉解题报告💥数的分解🤔一、思路:😎二、代码:💥前言 上午没写,下午写了会被朋友拉出去耍,被冷风吹到了,而且被他坑了,根本没有玩骑…...

Echarts 水波图实现
开发的项目中需要实现这样一个水波图,例如下图在echarts官网中找了很久没找到,后面是在Echarts社区中找到的,实现了大部分的样式,但是还有一些数据的展示没有实现。水波图的数值展示是默认整数百分比,我的需求是需要保…...

逻辑优化基础-shannon decomposition
1. 简介 在逻辑综合中,香农分解(Shannon decomposition)是一种常用的布尔函数分解方法。它将一个布尔函数分解为两个子函数的和,其中每个子函数包含一个布尔变量的取反和非取反的部分。 具体来说,假设对于一个布尔函…...

Java中线程池的创建与使用
前言:默认线程池的弊端在线程池应用中,参考阿里巴巴java开发规范:线程池不允许使用Executors去创建,不允许使用系统默认的线程池,推荐通过ThreadPoolExecutor的方式,这样的处理方式让开发的工程师更加明确&…...