原理使用AOP
元注解类
package com.meeno.common.lock;
import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target({ElementType.METHOD})
public @interface UserLock {
@AliasFor("name")
String value() default "USER_LOCK";
@AliasFor("value")
String name() default "USER_LOCK";
/**
* true 启用 false 禁用
* @return
*/
boolean enable() default true;
}
AOP配置类
package com.meeno.common.lock;
import com.meenoframework.common.filter.ThreadLocalClient;
import lombok.extern.java.Log;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* @description: AOPLock
* @author: Wzq
* @create: 2020-11-18 16:22
*/
@Aspect
@Component
@Log
public class AopLock {
@Autowired
private LockAbstract lockAbstract;
@Pointcut("@annotation(com.meeno.common.lock.UserLock)")//自定义元注解
public void pointcut() {
}
@Before("pointcut()")
public void before(JoinPoint joinPoint) throws NoSuchMethodException {
log.info("before!");
Object target = joinPoint.getTarget();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = target.getClass().getMethod(signature.getName(), signature.getParameterTypes());
UserLock annotation = method.getAnnotation(UserLock.class);
boolean enable = annotation.enable();
if(enable){
Long loginUserId = ThreadLocalClient.get().getId();
String name = annotation.value() + "_" +loginUserId;
lockAbstract.lock(name, 10L);
}
}
@After("pointcut()")
public void after(JoinPoint joinPoint) throws NoSuchMethodException {
log.info("after!");
Object target = joinPoint.getTarget();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = target.getClass().getMethod(signature.getName(), signature.getParameterTypes());
UserLock annotation = method.getAnnotation(UserLock.class);
boolean enable = annotation.enable();
if(enable){
Long loginUserId = ThreadLocalClient.get().getId();
String name = annotation.value() + "_" +loginUserId;
lockAbstract.unLock(name);
}
}
}
抽象锁接口
package com.meeno.common.lock;
/**
* @description: 锁接口
* @author: Wzq
* @create: 2020-11-18 16:36
*/
public interface LockAbstract {
/**
* 加锁
* @param name
* @return
*/
boolean lock(String name, Long timeoutSeconds);
/**
* 释放锁
* @param name
*/
void unLock(String name);
}
实现的redis加锁方式
package com.meeno.common.lock;
import com.meeno.common.utils.RedisLockUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* @description: redisLock锁
* @author: Wzq
* @create: 2020-11-18 16:38
*/
@Component
@Slf4j
public class RedisLock implements LockAbstract {
private static StringRedisTemplate stringRedisTemplate;
@Autowired
private void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate){
this.stringRedisTemplate = stringRedisTemplate;
}
@Override
public boolean lock(String name, Long timeoutSeconds) {
Boolean b = stringRedisTemplate.opsForValue().setIfAbsent(name, "lock",timeoutSeconds, TimeUnit.SECONDS);
//Boolean b1 = redisTemplate.opsForValue().setIfAbsent(key, value,timeout, TimeUnit.SECONDS);
if(b){
return true;
}else{
log.info("lock err!");
}
return false;
}
@Override
public void unLock(String name) {
stringRedisTemplate.delete(name);
log.info("releaseLock success!");
}
}