Redisson之——使用Redisson通过自定义注解实现分布式锁,使用Spring AOP简化分布式锁

但是每次使用分布式锁都要写类似上面的重复代码,有没有什么方法可以只关注核心业务逻辑代码的编写,即上面的"do some business"。下面介绍如何使用Spring AOP来实现这一目标。

使用Spring AOP简化分布式锁

定义注解@DistributedLock

@Target({ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface DistributedLock {

/**

  • 锁的名称。

  • 如果lockName可以确定,直接设置该属性。

*/

String lockName() default “”;

/**

  • lockName后缀

*/

String lockNamePre() default “”;

/**

  • lockName后缀

*/

String lockNamePost() default “lock”;

/**

  • 获得锁名时拼接前后缀用到的分隔符

  • @return

*/

String separator() default “.”;

/**

  • 获取注解的方法参数列表的某个参数对象的某个属性值来作为lockName。因为有时候lockName是不固定的。
    
  • 当param不为空时,可以通过argNum参数来设置具体是参数列表的第几个参数,不设置则默认取第一个。
    

*/

String param() default “”;

/**

  • 将方法第argNum个参数作为锁

*/

int argNum() default 0;

/**

  • 是否使用公平锁。

  • 公平锁即先来先得。

*/

boolean fairLock() default false;

/**

  • 是否使用尝试锁。

*/

boolean tryLock() default false;

/**

  • 最长等待时间。

  • 该字段只有当tryLock()返回true才有效。

*/

long waitTime() default 30L;

/**

  • 锁超时时间。

  • 超时时间过后,锁自动释放。

  • 建议:

  • 尽量缩简需要加锁的逻辑。

*/

long leaseTime() default 5L;

/**

  • 时间单位。默认为秒。

*/

TimeUnit timeUnit() default TimeUnit.SECONDS;

}

定义切面代码

@Aspect

@Component

public class DistributedLockAspect {

@Autowired

private DistributedLockTemplate lockTemplate;

@Pointcut(“@annotation(cn.sprinkle.study.distributedlock.common.annotation.DistributedLock)”)

public void DistributedLockAspect() {}

@Around(value = “DistributedLockAspect()”)

public Object doAround(ProceedingJoinPoint pjp) throws Throwable {

//切点所在的类

Class targetClass = pjp.getTarget().getClass();

//使用了注解的方法

String methodName = pjp.getSignature().getName();

Class[] parameterTypes = ((MethodSignature)pjp.getSignature()).getMethod().getParameterTypes();

Method method = targetClass.getMethod(methodName, parameterTypes);

Object[] arguments = pjp.getArgs();

final String lockName = getLockName(method, arguments);

return lock(pjp, method, lockName);

}

@AfterThrowing(value = “DistributedLockAspect()”, throwing=“ex”)

public void afterThrowing(Throwable ex) {

throw new RuntimeException(ex);

}

public String getLockName(Method method, Object[] args) {

Objects.requireNonNull(method);

DistributedLock annotation = method.getAnnotation(DistributedLock.class);

String lockName = annotation.lockName(),

param = annotation.param();

if (isEmpty(lockName)) {

if (args.length > 0) {

if (isNotEmpty(param)) {

Object arg;

if (annotation.argNum() > 0) {

arg = args[annotation.argNum() - 1];

} else {

arg = args[0];

}

lockName = String.valueOf(getParam(arg, param));

} else if (annotation.argNum() > 0) {

lockName = args[annotation.argNum() - 1].toString();

}

}

}

if (isNotEmpty(lockName)) {

String preLockName = annotation.lockNamePre(),

postLockName = annotation.lockNamePost(),

separator = annotation.separator();

StringBuilder lName = new StringBuilder();

if (isNotEmpty(preLockName)) {

lName.append(preLockName).append(separator);

}

lName.append(lockName);

if (isNotEmpty(postLockName)) {

lName.append(separator).append(postLockName);

}

lockName = lName.toString();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值