思路是:
- 获取锁使用 redis setnx key value 特性 :如果设置成功,返回 1 。 设置失败,返回 0 。
- 设置key 的过期时间
- 用完了删除key
- 采用 AOP 提高开发效率
- 自定义注解 包含 过期时间,等待时间,key
自定义注解
/**
* Created by linving on 2017/4/24.
*/
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RedisLock {
//等待时间
int maxWait() default 0;
//过期时间
int expiredTime() default 0;
// key
String[] keys() default {};
}
AOP实现
/**
* Created by linving on 2017/4/21.
* TODO
* 加鎖 采用注解
*/
@Component
@Aspect
public class CashLockInterceptor {
public static Logger logger = LoggerFactory.getLogger(CashLockInterceptor.class);
@Autowired
RedisOperator redisOperator;
/**
* 切面 加有 RedisLock 的 service 方法
*/
@Pointcut("execution(* com.xx.service..*.*(..)) && @annotation(com.xx.annotation.RedisLock)")
private void cutMethod() {
}
@Before("cutMethod()")
public void doAccessCheck(JoinPoint point) throws NoSuchMethodException {
logger.info("Before...");
}
@AfterReturning("cutMethod()")
public void doAfter(JoinPoint point) {
logger.info("AfterReturning...");
}
@After("cutMethod()")
public void after(JoinPoint point) {
logger.info("After...");
}
@AfterThrowing("cutMethod()")
public void doAfterThrow() {
logger.info("AfterThrowing...");
}
@Around("cutMethod()")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
String methodName = pjp.getSignature().getName();
Class<?> classTarget = pjp.getTarget().getClass();
Class<?>[] par = ((MethodSignature) pjp.getSignature()).getParameterTypes();
Method objMethod = classTarget.getMethod(methodName, par);
RedisLock redisLock = objMethod.getDeclaredAnnotation(RedisLock.class);
String[] keys = redisLock.keys();
int maxWait = redisLock.maxWait();
int expiredTime = redisLock.expiredTime();
Object result = null;
try {
logger.info("前置通知");
//获取锁
Arrays.stream(keys).forEach(key -> {
boolean flag = redisOperator.tryGetRedisLock(key, "", maxWait, expiredTime);
if(!flag){
//获取失败抛异常
throw new APIBusinessException(ErrorCodeEnum.CODE_SYSTEM_GET_MUCH);
}
});
//代理执行
result = pjp.proceed();
logger.info("后置通知");
} catch (Throwable e) {
//释放锁
Arrays.stream(keys).forEach(key->{
redisOperator.releaseLock(key,"");
});
logger.info("异常通知");
throw e;
}
logger.info("返回通知");
//释放锁
Arrays.stream(keys).forEach(key->{
redisOperator.releaseLock(key,"");
});
return result;
}
}
更多精彩内容:
http://jblog.top/