当前位置:   article > 正文

Java中动态修改注解的值_java修改注解的值

java修改注解的值

1. 描述

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

2. 步骤

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

3. 代码实现

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

3.1 主工具类

  1. import com.hz.common.aop.limit.RateLimit;
  2. import java.lang.reflect.Field;
  3. import java.lang.reflect.InvocationHandler;
  4. import java.lang.reflect.Proxy;
  5. import java.util.Map;
  6. /**
  7. * @author pp_lan
  8. * @date 2024/2/3
  9. */
  10. public class ReflectUtils {
  11. private ReflectUtils() {
  12. }
  13. public static void dynamicLocation(RateLimit rateLimit, String fileName, Object fieldValue) throws IllegalAccessException, NoSuchFieldException {
  14. if (rateLimit == null) {
  15. return;
  16. }
  17. InvocationHandler invocationHandler = Proxy.getInvocationHandler(rateLimit);
  18. Class<? extends InvocationHandler> aClass = invocationHandler.getClass();
  19. Field memberValues = aClass.getDeclaredField("memberValues");
  20. memberValues.setAccessible(true);
  21. Map<String, Object> menberValueMap = (Map<String, Object>) memberValues.get(invocationHandler);
  22. menberValueMap.put(fileName, fieldValue);
  23. }
  24. }

3.2 依赖

3.2.1 RateLimit

  1. import java.lang.annotation.*;
  2. /**
  3. * @author pp_lan
  4. */
  5. @Documented
  6. @Inherited
  7. @Target(ElementType.METHOD)
  8. @Retention(RetentionPolicy.RUNTIME)
  9. public @interface RateLimit {
  10. /**
  11. * 名称
  12. *
  13. * @return
  14. */
  15. String name();
  16. /**
  17. * 每分钟限流数量
  18. *
  19. * @return
  20. */
  21. int limitNum();
  22. }

3.2.2 切面处理

切面中需要动态获取注解

  1. @Component
  2. public class RateLimitAspect {
  3. private static final Logger LOGGER = LoggerFactory.getLogger(RateLimitAspect.class);
  4. private ConcurrentHashMap<String, RateLimiter> limitMap = new ConcurrentHashMap<>();
  5. @Pointcut("@annotation(com.hz.common.aop.limit.RateLimit) && @annotation(rateLimit)")
  6. public void pointCut(RateLimit rateLimit){}
  7. @Around(value = "pointCut(rateLimit)")
  8. public Object around(ProceedingJoinPoint joinPoint, RateLimit rateLimit) throws Throwable {
  9. // 此处动态获取注解值取代初始化的RateLimit值
  10. Object target = joinPoint.getTarget();
  11. MethodSignature sig = (MethodSignature) joinPoint.getSignature();
  12. Method currentMethod = target.getClass().getMethod(sig.getName(), sig.getParameterTypes());
  13. RateLimit newRateLimit = currentMethod.getAnnotation(RateLimit.class);
  14. LOGGER.info("[限流器{}]{}", newRateLimit.name(), newRateLimit.limitNum());
  15. boolean isLimited = limitByKey(newRateLimit.name(), newRateLimit.limitNum());
  16. if (isLimited) {
  17. throw new RateLimitException(String.format("【限流了】%s", newRateLimit.name()));
  18. }
  19. return joinPoint.proceed();
  20. }
  21. /**
  22. * 是否被限流
  23. *
  24. * @param key
  25. * @param limitNum
  26. * @return
  27. */
  28. private boolean limitByKey(String key, Integer limitNum) {
  29. ...
  30. }
  31. }

3.3 使用

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

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

4. 效果

4.1 初始化的桶大小

4.2 限流提示

4.3 动态更改流量值

4.4 重新访问

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/569616
推荐阅读
相关标签
  

闽ICP备14008679号