首页 > 编程语言 >自定义注解使用在AOP切面编程里

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

时间:2022-12-17 20:56:20浏览次数:43  
标签:自定义 AOP springframework public 切面 org redisLockAnnotation import annotation

自定义注解:

@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.

标签:自定义,AOP,springframework,public,切面,org,redisLockAnnotation,import,annotation
From: https://www.cnblogs.com/zhuwenjoyce/p/16989518.html

相关文章

  • springboot配置自定义objectMapper
      packagecom.my.config;importcom.fasterxml.jackson.annotation.JsonInclude;importcom.fasterxml.jackson.core.JsonGenerator;importcom.fasterxml.jackso......
  • 【云原生】Prometheus 自定义告警规则
    目录一、概述二、告警实现流程三、告警规则1)告警规则配置1)监控服务器是否在线3)告警数据的状态四、实战操作1)下载node_exporter2)启动node_exporter3)配置Prometheus加载nod......
  • springboot启动读取配置文件过程&自定义配置文件处理器
        最近看到看到spring的配置文件放在了resources/config/application.yal文件内部,第一次见。就想的研究下,springboot启动读取配置文件的过程。1.启动过程org.spring......
  • <三>自定义删除器
    unique_ptr的成员函数在上一篇博客中几乎全部涵盖,其实还有一个很有踢掉,即std::unique_ptr::get_deleter字面已经很明显了,就获得deleter智能指针采通过引用计数我们能解决......
  • 【SpringBoot】封装自定义的starter
    一、参考资料​​SpringBoot封装自己的Starter-码农教程​​​​[Gradle]发布构件到本地仓库​​​​Gradle插件之maven-publish:发布androidlibrary到maven仓库-知乎......
  • android自定义属性
    1、引言对于自定义属性,大家肯定都不陌生,遵循以下几步,就可以实现:1.自定义一个CustomView(extendsView)类2.编写values/attrs.xml,在其中编写styleable和item等标签元素3.......
  • android自定义listview实现header悬浮框效果
    之前在使用iOS时,看到过一种分组的View,每一组都有一个Header,在上下滑动的时候,会有一个悬浮的Header,这种体验觉得很不错,请看下图:上图中标红的1,2,3,4四张图中,当向上滑动时,仔细......
  • vba自定义函数
    excel不是最新版的,没有textjoin函数,写两个用。函数一:pastestr():优点:简单,第二个参数可以省略;缺点:只能是一个连续区域,或小括号内的(多个不连续单一元格)。1Functionp......
  • 企业级自定义表单引擎解决方案(十八)--列表视图属性设置
    表格对于后台管理类的系统来说,至关重要,系统大多数功能都需要以表格的方式展示业务内容,系统开发人员多数时间也是围绕着表格进行业务编码,接触过很多后台管理系统的框架,我个......
  • 自研ORM框架 实现类似EF Core Include 拆分查询 支持自定义条件、排序、选择
    Baozi,I'mMr.ZhongIliketobrushTikTok,Iknowthatanchorsliketocallitthat,haha!Recently,Ihaven'tbeensobusy,andittookalmostadaytoaddso......