1、为什么需要 声明式的分布式锁
编程式分布式锁每次实现都要单独实现,但业务量大功能复杂时,使用编程式分布式锁无疑是痛苦的,而声明式分布式锁不同,声明式分布式锁属于无侵入式,不会影响业务逻辑的实现。
我的为什么要用:使用简单,提升开发效率
2、怎么实现
使用spring aop + 自定义注解来实现
下面来看下spring boot + 自定义注解 如何实现一个声明式的分布式锁
3、看代码
第一步、引入aop 需要 jar包
<!-- SpringBoot AOP start -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<!-- SpringBoot AOP end -->
第二步、@EnableAspectJAutoProxy 开启AOP
@EnableAspectJAutoProxy
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
第三步:自定义DistributionLock注解
import java.lang.annotation.*;
/**
* 通常 和com.example.demo.annotation.DistributionLockParam 注解配合使用,降低锁粒度
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DistributionLock {
/**
* 分布式锁key
*/
String key();
/**
* 尝试获得锁的时间(单位:毫秒),默认值:5000毫秒
*
* @return 锁key过期时间
*/
long tryLockTime() default 5000;
/**
* 尝试获得锁后,持有锁的时间(单位:毫秒),默认值:60000毫秒
*
* @return
*/
long holdLockTime() default 60000;
/**
* 分布式锁key 的分隔符(默认 :)
*/
String delimiter() default ":";
}//欢迎大家进Java学习交流君样:1142951706 一起交流 一起吹水~
第四步:自定义DistributionLockParam注解
/**
* 分布式锁参数
* 这个注解,是给DistributionLock用来控制锁粒度的
*/
@Target({
ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DistributionLockParam {
}
第五步:定义分布式锁AOP配置第五步:定义分布式锁AOP配置
import com.example.demo.annotation.DistributionLock;
import com.example.demo.annotation.DistributionLockParam;
import com.example.demo.entity.Resp;
import com.example.demo.redisLock.LockParam;
import com.example.demo.redisLock.RedisLock;
import lombok.extern.slf4j.Slf4j;
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.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/**
* 对springboot中aop切面编程的测试
*/
//切面类
@Aspect
@Component
@Slf4j
@Order(Ordered.HIGHEST_PRECEDENCE)
public class RedisAopAspect {
public RedisAopAspect(){
log.info("分布锁 aop init");
}
/***
* 定义切入点
*/
@Pointcut("execution(@com.example.demo.annotation.DistributionLock * *(..))")
public void pointCut(){
}
@Around(value = "pointCut()")
public Object aroundMethod(ProceedingJoinPoint pjp) {
MethodSignature signature = (MethodSignature) pjp.getSignature();
Method method = signature.getMethod();
/AOP 能取得的信息 start
// log.info("目标方法名为:{}",pjp.getSignature().getName());
// log.info("目标方法所属类的简单类名:{}" , pjp.getSignature().getDeclaringType().getSimpleName());
// log.info("目标方法所属类的类名:{}", pjp.getSignature().getDeclaringTypeName());
// log.info("目标方法声明类型:{}" , Modifier.toString(pjp.getSignature().getModifiers()));
// log.info("目标方法返回值类型:{}" , method.getReturnType());
// //获取传入目标方法的参数
// Object[] args = pjp.getArgs();
// for (int i = 0; i < args.length; i++) {
// log.info("第{}个参数为:{}" ,(i + 1) , args[i]);
// }
// log.info("被代理的对象:{}" , pjp.getTarget());
// log.info("代理对象自己:{}" , pjp.getThis());
/AOP 能取得的信息 end
//取得注解对象数据
DistributionLock lock = method.getAnnotation(DistributionLock.class);
//分布式锁实际的key
String lockKey = getRealDistributionLockKey(pjp,lock);
//创建分布式锁对象 start
LockParam lockParam = new