spring boot 自定义注解 实现本地锁

「爱情、让人受尽委屈。」 2022-12-19 16:17 264阅读 0赞

技术点

  1. AOP
  2. 注解声明
  3. 自动配置

声明注解

  1. import java.lang.annotation.*;
  2. @Target(ElementType.METHOD)
  3. @Retention(RetentionPolicy.RUNTIME)
  4. @Documented
  5. @Inherited
  6. public @interface LocalLock {
  7. String key() default "";
  8. }

key为锁标识

AOP 实现注解

  1. import cn.hutool.cache.Cache;
  2. import cn.hutool.cache.CacheUtil;
  3. import cn.hutool.core.date.DateUnit;
  4. import cn.hutool.core.util.NumberUtil;
  5. import cn.hutool.core.util.ReflectUtil;
  6. import cn.hutool.core.util.StrUtil;
  7. import com.alibaba.fastjson.JSON;
  8. import com.guodun.aiosign.tools.lock.LocalLock;
  9. import lombok.extern.slf4j.Slf4j;
  10. import org.aspectj.lang.ProceedingJoinPoint;
  11. import org.aspectj.lang.annotation.Around;
  12. import org.aspectj.lang.annotation.Aspect;
  13. import org.aspectj.lang.reflect.MethodSignature;
  14. import org.springframework.context.annotation.Configuration;
  15. import org.springframework.util.StringUtils;
  16. import java.lang.reflect.Method;
  17. @Aspect
  18. @Configuration
  19. @Slf4j
  20. public class LocalLockInterceptor {
  21. private static Cache<String, String> lockCache = CacheUtil.newLFUCache(200, DateUnit.SECOND.getMillis() * 10);
  22. @Around("@annotation(com.guodun.aiosign.tools.lock.LocalLock)")
  23. public Object interceptor(ProceedingJoinPoint pjp) {
  24. MethodSignature signature = (MethodSignature) pjp.getSignature();
  25. Method method = signature.getMethod();
  26. LocalLock localLock = method.getAnnotation(LocalLock.class);
  27. String key = getKey(localLock.key(), pjp.getArgs());
  28. if (!StringUtils.isEmpty(key)) {
  29. if (lockCache.containsKey(key)) {
  30. log.debug("发生死锁 : {} ",key);
  31. checkLock(key);
  32. }else {
  33. lockCache.put(key, key);
  34. }
  35. }
  36. try {
  37. return pjp.proceed();
  38. } catch (Throwable throwable) {
  39. throw new RuntimeException("服务器异常");
  40. } finally {
  41. // 请求结束后解除锁
  42. if (!StringUtils.isEmpty(key)) lockCache.remove(key);
  43. }
  44. }
  45. private void checkLock(String key) {
  46. try {
  47. for (int i = 0; i < 20; i++) {
  48. if (!lockCache.containsKey(key)) return;
  49. Thread.sleep(500);
  50. }
  51. }catch (InterruptedException e) {
  52. e.printStackTrace();
  53. }
  54. if (lockCache.containsKey(key)) throw new RuntimeException("请勿重复请求");
  55. }
  56. private String getKey(String keyExpress, Object[] args) {
  57. String[] keys = StrUtil.splitToArray(keyExpress,'.');
  58. log.debug("参数 {} ", JSON.toJSONString(keys));
  59. if (keys.length>0&&args.length>0){
  60. String args_str = keys[0];
  61. if(!NumberUtil.isInteger(args_str)) return null;
  62. int args_index = Integer.valueOf(args_str);
  63. if (args_index>args.length)return null;
  64. if(keys.length<2) {
  65. log.info("value : {} ",args[args_index-1].toString());
  66. return args[args_index-1].toString();
  67. }
  68. Object value = ReflectUtil.getFieldValue(args[args_index-1],keys[1]);
  69. log.info("value : {} ",value.toString());
  70. return value.toString();
  71. }
  72. return null;
  73. }
  74. }

自动配置(spring boot)

在这里插入图片描述

  1. #配置自定义Starter的自动化配置
  2. org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.keepgoon.tools.lock.local.LocalLockInterceptor

发表评论

表情:
评论列表 (有 0 条评论,264人围观)

还没有评论,来说两句吧...

相关阅读