如何使用自定义注解实现redisson分布式锁

自定义分布式锁注解

Redisson分布式锁自定义注解

import java.lang.annotation.*;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DistributedLock {
    /**
     * 锁的名称
     */
    String value() default "redisson";

    /**
     * 锁的有效时间
     */
    int expireTime() default 10;
}

分布式锁AOP

import com.it.redis.service.RedissonLockService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * @description: Redisson分布式锁注解AOP
 */
@Slf4j
@Aspect
@Component
public class DistributedLockAspect {

    @Autowired(required = false)
    RedissonLockService redissonLockService;

    @Around("@annotation(distributedLock)")
    public void around(ProceedingJoinPoint joinPoint, DistributedLock distributedLock) {
    	log.info("分布式锁-lock");
        //获取锁名称
        String lockName = distributedLock.value();
        //获取超时时间,默认10秒
        int expireTime= distributedLock.expireTime();
        boolean isLock = redissonLockService.tryLock(lockName, expireTime);
        try {
            if (isLock){
                log.info("加锁成功,开始执行业务...");
                joinPoint.proceed();
                log.info("业务执行完成.");
            }else {
                log.info("尝试获取锁失败, 稍后重试!");
                TimeUnit.MILLISECONDS.sleep(200);
            }
        } catch (Throwable throwable) {
            log.error("加锁失败: ", throwable);
            throwable.printStackTrace();
        } finally {
            //如果该线程还持有该锁,那么释放该锁。如果该线程不持有该锁,说明该线程的锁已到过期时间,自动释放锁
            if (redissonLockService.isHeldByCurrentThread(lockName)) {
                redissonLockService.unlock(lockName);
            }
        }
        log.info("分布式锁-unlock");
    }
}

实现方法

import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RBucket;
import org.redisson.api.RLock;
import org.redisson.api.RTopic;
import org.redisson.client.codec.StringCodec;
import org.redisson.codec.JsonJacksonCodec;
import org.redisson.codec.SerializationCodec;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;

import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;

/**
 * @description: Redisson方法
 */
@Slf4j
@ConditionalOnBean(Redisson.class)
public class RedissonLockService {

    @Autowired
    private Redisson redisson;

    /**
     * 加锁操作 (设置锁的有效时间)
     *
     * @param lockName   锁名称
     * @param expireTime 锁有效时间
     */
    public void lock(String lockName, long expireTime) {
        RLock rLock = redisson.getLock(lockName);
        rLock.lock(expireTime, TimeUnit.SECONDS);
    }

    /**
     * 加锁操作 (锁有效时间采用默认时间30秒)
     *
     * @param lockName 锁名称
     */
    public void lock(String lockName) {
        RLock rLock = redisson.getLock(lockName);
        //默认看门狗3*10s续期,中间完成任务不续期
        rLock.lock();
    }

    /**
     * 加锁操作(tryLock锁,没有等待时间)
     *
     * @param lockName  锁名称
     * @param expireTime 锁有效时间
     */
    public boolean tryLock(String lockName, long expireTime) {

        RLock rLock = redisson.getLock(lockName);
        boolean getLock = false;
        try {
            getLock = rLock.tryLock(expireTime, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            log.error("获取Redisson分布式锁[异常],lockName=" + lockName, e);
            e.printStackTrace();
            return false;
        }
        return getLock;
    }

    /**
     * 加锁操作(tryLock锁,有等待时间)
     *
     * @param lockName  锁名称
     * @param leaseTime 锁有效时间
     * @param waitTime  等待时间
     */
    public boolean tryLock(String lockName, long leaseTime, long waitTime) {

        RLock rLock = redisson.getLock(lockName);
        boolean getLock = false;
        try {
            getLock = rLock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            log.error("获取Redisson分布式锁[异常],lockName=" + lockName, e);
            e.printStackTrace();
            return false;
        }
        return getLock;
    }

    /**
     * 解锁
     *
     * @param lockName 锁名称
     */
    public void unlock(String lockName) {
        redisson.getLock(lockName).unlock();
    }

    /**
     * 判断该锁是否已经被线程持有
     *
     * @param lockName 锁名称
     */
    public boolean isLock(String lockName) {
        RLock rLock = redisson.getLock(lockName);
        return rLock.isLocked();
    }


    /**
     * 判断该线程是否持有当前锁
     *
     * @param lockName 锁名称
     */
    public boolean isHeldByCurrentThread(String lockName) {
        RLock rLock = redisson.getLock(lockName);
        return rLock.isHeldByCurrentThread();
    }

    /**
     * 存储缓存
     */
    public <T> void setBucket(String key, T value) {
        RBucket<T> bucket = redisson.getBucket(key, StringCodec.INSTANCE);
        bucket.set(value);
    }

    /**
     * 存储过期缓存
     */
    public <T> void setBucket(String key, T value, long expired) {
        RBucket<T> bucket = redisson.getBucket(key, JsonJacksonCodec.INSTANCE);
        bucket.set(value, expired, TimeUnit.SECONDS);
    }

    /**
     * 读取缓存
     */
    public <T> T getBucket(String key, Class<T> clazz) {
        RBucket<T> bucket = redisson.getBucket(key, JsonJacksonCodec.INSTANCE);
        return bucket.get();
    }

    /**
     * 移除缓存
     */
    public void removeBucket(String key) {
        redisson.getBucket(key).delete();
    }

    /**
     * 判断缓存是否存在
     */
    public boolean existsBucket(String key) {
        return redisson.getBucket(key).isExists();
    }

    /**
     * 发布消息
     */
    public <T> long publishMessage(String topic, T message) {
        //T要实现序列化接口
        RTopic rTopic = redisson.getTopic(topic, new SerializationCodec());
        long l = rTopic.publish(message);
        log.info("message push success.");
        return l;
    }

    /**
     * 订阅消息
     */
    public <T> void receiveMessage(String topic, Class<T> clazz, BiConsumer<? super CharSequence, T> consumer) {
        RTopic rTopic = redisson.getTopic(topic, new SerializationCodec());
        rTopic.addListenerAsync(clazz, (charSequence, msg) -> {
                    //消费的具体内容
                    consumer.accept(charSequence, msg);
                    log.info("message consumer complete.");
                }
        );
    }

}

你可能感兴趣的:(分布式,java,spring)