Java中动态修改注解的值

1. 描述

部分场景需要动态修改注解的值。例如,我们使用自定义注解控制接口流量,如果需要动态修改流量值,可以使用反射的方法实现。

2. 步骤

  • 获取注解
  • 从注解中获取memberValues属性(map)
  • 使用put方法更新对象的值

3. 代码实现

该部分代码主要是基于流量控制的功能demo,使用反射动态修改@RateLimit注解达到动态修改流量的目的。此章节节选了反射修改值的代码予以分享。

3.1 主工具类

import com.hz.common.aop.limit.RateLimit;import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Map;/*** @author pp_lan* @date 2024/2/3*/
public class ReflectUtils {private ReflectUtils() {}public static void dynamicLocation(RateLimit rateLimit, String fileName, Object fieldValue) throws IllegalAccessException, NoSuchFieldException {if (rateLimit == null) {return;}InvocationHandler invocationHandler = Proxy.getInvocationHandler(rateLimit);Class<? extends InvocationHandler> aClass = invocationHandler.getClass();Field memberValues = aClass.getDeclaredField("memberValues");memberValues.setAccessible(true);Map<String, Object> menberValueMap = (Map<String, Object>) memberValues.get(invocationHandler);menberValueMap.put(fileName, fieldValue);}
}

3.2 依赖

3.2.1 RateLimit

import java.lang.annotation.*;/*** @author pp_lan*/
@Documented
@Inherited
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RateLimit {/*** 名称** @return*/String name();/*** 每分钟限流数量** @return*/int limitNum();}

3.2.2 切面处理

切面中需要动态获取注解

@Component
public class RateLimitAspect {private static final Logger LOGGER = LoggerFactory.getLogger(RateLimitAspect.class);private ConcurrentHashMap<String, RateLimiter> limitMap = new ConcurrentHashMap<>();@Pointcut("@annotation(com.hz.common.aop.limit.RateLimit) && @annotation(rateLimit)")public void pointCut(RateLimit rateLimit){}@Around(value = "pointCut(rateLimit)")public Object around(ProceedingJoinPoint joinPoint, RateLimit rateLimit) throws Throwable {// 此处动态获取注解值取代初始化的RateLimit值Object target = joinPoint.getTarget();MethodSignature sig = (MethodSignature) joinPoint.getSignature();Method currentMethod = target.getClass().getMethod(sig.getName(), sig.getParameterTypes());RateLimit newRateLimit = currentMethod.getAnnotation(RateLimit.class);LOGGER.info("[限流器{}]{}", newRateLimit.name(), newRateLimit.limitNum());boolean isLimited = limitByKey(newRateLimit.name(), newRateLimit.limitNum());if (isLimited) {throw new RateLimitException(String.format("【限流了】%s", newRateLimit.name()));}return joinPoint.proceed();}/*** 是否被限流** @param key* @param limitNum* @return*/private boolean limitByKey(String key, Integer limitNum) {...}}

3.3 使用

5-7行获取注解,并修改注解中属性的值

@RequestMapping("/updateLimitRate")
public Response editLimitRate(Integer methodType, Integer limitNum) throws NoSuchMethodException, NoSuchFieldException, IllegalAccessException {String methodName = methodType == 1 ? "queryAllUser": "test";Method method = UserService.class.getMethod(methodName);RateLimit annotation = method.getAnnotation(RateLimit.class);ReflectUtils.dynamicLocation(annotation, "limitNum", limitNum);return Response.ok();
}

4. 效果

4.1 初始化的桶大小

4.2 限流提示

4.3 动态更改流量值

4.4 重新访问

不再限流,接口可以继续正常访问了。

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

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

相关文章

YOLO部署实战(3):Darknet训练模型权重

1 一些概念和问题 YOLO中的darknet到底指的是什么&#xff1f; darknet到底是一个类似于TensorFlow、PyTorch的框架&#xff0c;还是一个类似于AlexNet、VGG的模型&#xff1f; 其实都是。YOLO作者自己写的一个深度学习框架叫darknet&#xff08;见YOLO原文2.2部分&#xff…

Hexo设置少量固定的动态背景图

文章目录 前言先准备素材问题分析代码实现逻辑写在哪先搭建基本框架然后添加图片链接动画效果 前言先准备素材问题分析代码实现逻辑写在哪先搭建基本框架然后添加图片链接动画效果 前言 在以前的这篇文章中&#xff0c;我们设置了一些动态背景。 这次我们加一丁点优化&#x…

MySQL 用户管理

重点&#xff1a; 视图&#xff0c;函数&#xff0c;存储过程&#xff0c;触发器&#xff0c;事件&#xff08; 了解 &#xff09; 用户管理&#xff0c;密码管理 grant revoke 权限管理 MySQL 架构&#xff08; 了解 &#xff09; 存储引擎&#xff1a;MyISAM 和 InnoDB …

展馆设计的必备要素有哪些

1、空间的设计 展馆要想配得上优秀这两个字眼&#xff0c;那么比较基本的表现就是要具有美感&#xff0c;要规划&#xff0c;合理美观的造型&#xff0c;并在此基础上重视互动融合&#xff0c;既要拥有特色具有创意的风格&#xff0c;又要能够和整个空间和谐又统一。布展内容结…

Python入门:生成器迭代器

一、列表生成式 现在有个需求&#xff0c;列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]&#xff0c;要求你把列表里的每个值加1&#xff0c;怎么实现&#xff1f;你可能会想到2种方式 二逼青年版 1 2 3 4 a [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] b [] for i in a:b.append(i1) print(b) …

ele-h5项目使用vue3+vite+vant4开发:第四节、业务组件-SearchView组件开发

需求分析 展示切换动画搜索框输入文字&#xff0c;自动发送请求搜索结果展示搜索状态维护历史搜索展示&#xff0c;点击历史搜索后发送请求历史搜索更多切换动画效果 <script setup lang"ts"> import OpSearch from /components/OpSearch.vue import { ref } f…

Sequine - Sequencing Animation and Visual Scripting

Sequine是Unity的通用序列工具和可视化脚本。您还可以按需播放动画片段,而不受 Animator 控制器的限制! 以下是可以使用工具进行的工作: 直接序列动画剪辑,不受animator控制器的限制 用可堆叠行为序列文本动画 序列脚本功能/命令执行 序列可以存在于任何类型的Unity对象中,…

05 MP之ActiveRecord模式+SimpleQuery

1. ActiveRecord ActiveRecord(活动记录&#xff0c;简称AR)&#xff0c;是一种领域模型模式&#xff0c;特点是一个模型类对应关系型数据库中的一个表&#xff0c;而模型类的一个实例对应表中的一行记录。 其目标是通过围绕一个数据对象, 进行全部的CRUD操作。 1.1 让实体类…

nginx初学者指南

一、启动、停止和重新加载配置 前提&#xff1a;先要启动nginx 在Windows上启动nginx的步骤如下&#xff1a; 1. 下载并安装nginx。可以从nginx官网下载适合自己操作系统的版本&#xff0c;一般是zip压缩包&#xff0c;解压到指定目录中。 2. 进入nginx的安装目录&#xff…

【LeetCode】每日一题 2024_2_4 Nim 游戏(找规律,博弈论)

文章目录 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01;题目&#xff1a;Nim 游戏题目描述代码与解题思路 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01; 题目&#xff1a;Nim 游戏 题目链接&#xff1a;292. Nim 游戏 题目描述 代码与解题…

Leetcode—32. 最长有效括号【困难】(动态规划及ranges::max()使用)

2024每日刷题&#xff08;110&#xff09; Leetcode—32. 最长有效括号 栈实现代码 class Solution { public:int longestValidParentheses(string s) {stack<int> st;st.push(-1);int n s.size();int maxn 0;for(int i 0; i < n; i) {if(s[i] () {st.push(i);}…

【20240131】USB相机(查看设备列表、打开设备)

USB相机采集 1、v4l2查看设备列表2、查看具体设备信息3、在桌面打开USB相机 1、v4l2查看设备列表 打开终端&#xff0c;输入&#xff1a;v4l2-ctl --list-devices usb设备在Webcam: Webcam栏&#xff0c;分别是video9和video10&#xff0c;下一步&#xff1a;确定哪一个是接入…