自定义注解使用在AOP切面编程里

自定义注解:

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RedisDistributeLock {

    String key();

    int leastLockMs() default 1500;
}

使用自定义注解:

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
@Component
@RequiredArgsConstructor
@ConditionalOnExpression(value = "${enable.job:true}")
public class MyJob {

    final MyService myService;

    @Scheduled(cron = "${cron.MyJob}")
    @RedisDistributeLock(key = "redis.lock.MyJob")
    public void executeJob() {
        log.info("start MyJob")
    }
}

 AOP拦截:

package com.my.aop;

import lombok.RequiredArgsConstructor;
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.annotation.AnnotatedElementUtils;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.time.temporal.ChronoUnit;

@Slf4j
@Aspect
@Component
@RequiredArgsConstructor
public class RedisDistributeLockAopForJob {
    final RedisTemplate<String, Object> redisTemplate;
    final ReactiveRedisTemplate<String, Object> reactiveRedisTemplate;

    @Pointcut(value = "@annotation(com.my.aop.RedisDistributeLock)")
    public void scheduleDistributeLock() {
    }

    @Around("scheduleDistributeLock()")
    public Object handle(ProceedingJoinPoint pjp) throws Throwable {
        RedisDistributeLock redisLockAnnotation = AnnotatedElementUtils
                .getMergedAnnotation(
                        ((MethodSignature) pjp.getSignature()).getMethod()
                        , RedisDistributeLock.class
                );
        try {
            assert redisLockAnnotation != null;
            if (Boolean.TRUE.equals(redisTemplate.opsForValue()
                    .setIfAbsent(redisLockAnnotation.key(), Thread.currentThread().getId(), Duration.ofMillis(redisLockAnnotation.leastLockMs())))) {
                log.info("aop lock success. job name = {}, least lock {} ms", redisLockAnnotation.key(), redisLockAnnotation.leastLockMs());

                long startLockTimeMS = System.currentTimeMillis();
                Object returnObj = pjp.proceed();
                long spendMs = System.currentTimeMillis() - startLockTimeMS;
                long gapMs = (long) redisLockAnnotation.leastLockMs() - spendMs;

                if (gapMs <= 0) {
                    //Boolean isDelete = redisTemplate.delete(redisLockAnnotation.key());
                    log.info("aop is finish and delete redis key {} is {}", redisLockAnnotation.key(), true);
                } else {
                    log.info("aop is finish and expire time is {} s, job name = {}", this.getExpireSecondByKey(redisLockAnnotation.key()), redisLockAnnotation.key());
                }

                return returnObj;
            } else {
                log.info("aop lock fail because expire time is {} s on job {}", this.getExpireSecondByKey(redisLockAnnotation.key()), redisLockAnnotation.key());
            }
        } catch (Throwable throwable) {
            log.error("catch aop error. job name = {}", redisLockAnnotation.key(), throwable);
            throw throwable;
        }
        return null;
    }

    private Long getExpireSecondByKey(String redisKey) {
        return  reactiveRedisTemplate.getExpire(redisKey).defaultIfEmpty(Duration.ZERO).block(Duration.ofMillis(100)).get(ChronoUnit.SECONDS);
    }

}

 

end.

posted on 2022-12-17 20:44  梦幻朵颜  阅读(57)  评论(0编辑  收藏  举报