注解的方式实现redis分布式锁
2017-11-06 18:08
423 查看
创建redisLock注解:
拦截器逻辑:
使用方式:只需要在需要使用redis锁的方法上添加@RedisLock注解,并输入redis锁的前缀字段,过时时间和时间单位有默认值,而方法上的第一个String类型的参数为锁的key的第二段。
import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.concurrent.TimeUnit; /** * redis锁注解 * @author MAZHEN */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) @Documented public @interface RedisLock { String lockPrefix() default ""; long timeOut() default 60; TimeUnit timeUnit() default TimeUnit.SECONDS; }
拦截器逻辑:
import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import org.aspectj.apache.bcel.classfile.Constant; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import com.spring.mongo.annotation.RedisLock; /** * redis锁拦截器实现 * @author MAZHEN */ @Aspect @Component public class RedisLockInterceptor { private static final Integer MAX_RETRY_COUNT = 10; private static final String LOCK_PRE_FIX = "lockPreFix"; private static final String TIME_OUT = "timeOut"; @Autowired private RedisManager redisManager; @Pointcut("@annotation(com.spring.mongo.annotation.RedisLock)") public void redisLockAspect(){} @Around("redisLockAspect()") public Map<String, Object> lockAroundAction(ProceedingJoinPoint proceeding){ //获取redis锁 Map<String, Object> getLockResult = this.getLock(proceeding,0,System.currentTimeMillis()); } /** * 获取锁 * @param proceeding * @return */ private Map<String, Object> getLock(ProceedingJoinPoint proceeding,int count,long currentTime){ //获取注解中的参数 Map<String, Object> annotationArgs = this.getAnnotationArgs(proceeding); String lockPrefix = (String) annotationArgs.get(LOCK_PRE_FIX); long expire = (long) annotationArgs.get(TIME_OUT); String key = this.getFirstArg(proceeding); if(StringUtils.isEmpty(lockPrefix) || StringUtils.isEmpty(key)){ return this.argErrResult("锁前缀或业务参数不能为空"); } String lockName = lockPrefix+"_"+key; String value = String.valueOf(currentTime); if(CommonRedisUtils.setNx(lockName,value) == 1){ //获取锁成功 CommonRedisUtils.expire(lockName,expire); return this.buildSuccessResult(); }else { //获取锁失败,为防止其它线程正在设置过时时间时误删,添加第一个条件 if((System.currentTimeMillis()-currentTime>5000) &&(CommonRedisUtils.ttl(lockName)<0 ||System.currentTimeMillis()-currentTime>expire)){ //强制删除锁,并尝试再次获取锁 CommonRedisUtils.delete(lockName); if(count<MAX_RETRY_COUNT){ return getLock(proceeding,count++,currentTime); } } return this.buildGetLockErrorResult("请重试!!!"); } } /** * 获取锁参数 * @param proceeding * @return */ private Map<String, Object> getAnnotationArgs(ProceedingJoinPo b09a int proceeding){ Class target = proceeding.getTarget().getClass(); Method[] methods = target.getMethods(); String methodName = proceeding.getSignature().getName(); for (Method method : methods) { if(method.getName().equals(methodName)){ Map<String, Object> result = new HashMap<String, Object>(); RedisLock redisLock = method.getAnnotation(RedisLock.class); result.put(LOCK_PRE_FIX,redisLock.lockPrefix()); result.put(TIME_OUT, redisLock.timeUnit().toSeconds(redisLock.timeOut())); return result; } } return null; } /** * 获取第一个String类型的参数为锁的业务参数 * @param proceeding * @return */ public String getFirstArg(ProceedingJoinPoint proceeding){ Object[] args = proceeding.getArgs(); if(args != null && args.length>0){ for (Object object : args) { String type = object.getClass().getName(); if("java.lang.String".equals(type)){ return (String)object; } } } return null; } public Map<String, Object> argErrResult(String mes){ Map<String, Object> result = new HashMap<String, Object>(); //TODO //result.put("code", "9"); result.put("msg", mes); return result; } public Map<String, Object> buildGetLockErrorResult(String mes){ Map<String, Object> result = new HashMap<String, Object>(); //TODO //result.put("code", "9"); result.put("msg", mes); return result; } public Map<String, Object> buildSuccessResult(){ Map<String, Object> result = new HashMap<String, Object>(); //TODO //result.put("code", "1"); result.put("msg", "处理成功"); return result; } }
使用方式:只需要在需要使用redis锁的方法上添加@RedisLock注解,并输入redis锁的前缀字段,过时时间和时间单位有默认值,而方法上的第一个String类型的参数为锁的key的第二段。
相关文章推荐
- 使用Spring的注解方式实现AOP的细节
- 注解和声明方式实现AOP
- hibernate3注解方式实现一对多映射
- spring mybatis 用注解方式实现动态切切换数据源
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- Spring MVC拦截器+注解方式实现防止表单重复提交
- 使用Spring的注解方式实现AOP
- springMvc(3)---注解方式实现登陆
- 注解方式增强(实现登录日志录入数据库)(前置增强+后置增强)
- hibernate注解方式实现一对多映射
- spring aop相关概念和xml与注解实现方式
- spring 注解方式实现依赖注入
- 使用AspectJ提供的注解方式实现aop
- 原生websocket简单实现即时通信功能-注解方式
- spring注解方式自动注入接口的实现子类
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- aop注解方式实现日志管理
- springMVC学习笔记六(注解方式实现控制器)