自定义注解-方法重试@RetryProcess
背景
在项目开发中,有时候会出现接口调用失败,本身调用又是异步的,如果是因为一些网络问题请求超时,总想可以重试几次把任务处理掉。
一些RPC框架,比如dubbo都是有重试机制的,但是并不是每一个项目多会使用dubbo框架,常规的小项目有时候直接使用http进行不同项目之间的交互。
思路
使用spring aop和自定义注解来,建立一套重试机制。
根据切入点和自定义注解,来完成重试工作。
自定义注解
定义注解
package com.github.feifuzeng.study.annotation;
import org.springframework.stereotype.Component;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author feifz
* @version 1.0.0
* @Description 重试机制自定义注解
* @createTime 2019年06月20日 14:05:00
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface RetryProcess {
int value() default 1;
int sleep() default 1000;
}
注解中value参数为重试次数,默认为1,sleep为重试间隔,默认为1000毫秒。
定义切面
package com.github.feifuzeng.study.annotation;
/**
* @author feifz
* @version 1.0.0
* @Description 重试注解切面
* @createTime 2019年06月20日 14:07:00
*/
import lombok.extern.log4j.Log4j2;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint;
import org.springframework.stereotype.Component;
import java.util.concurrent.atomic.AtomicInteger;
@Aspect
@Component
@Log4j2
public class RetryProcessAspect {
private AtomicInteger atomicInteger = new AtomicInteger(0);
@AfterThrowing(pointcut=("@annotation(com.github.feifuzeng.study.annotation.RetryProcess)"))
public void tryAgain(JoinPoint point) {
try {
MethodSignature methodSignature = (MethodSignature) point.getSignature();
RetryProcess retryProcess = methodSignature.getMethod().getAnnotation(RetryProcess.class);
if (atomicInteger.intValue() < retryProcess.value()) {
int i = atomicInteger.incrementAndGet();
Thread.sleep(retryProcess.sleep() * i);
log.debug("开始重试第" + i + "次");
MethodInvocationProceedingJoinPoint methodPoint = ((MethodInvocationProceedingJoinPoint) point);
methodPoint.proceed();
}
} catch (Throwable throwable) {
tryAgain(point);
}
}
}
使用示例
@RetryProcess(value = 2,sleep = 2000)
public List<User> findList() {
return userMapper.queryUserList();
}
该自定义注解用于方法上,当改方法在执行过程中存在异常,不管是系统异常还是手动抛出的业务异常,均可实现重试。
知识课堂
JoinPoint 对象
JoinPoint对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,就可以获取到封装了该方法信息的JoinPoint对象.
常用api:
| 方法名 | 功能 |
|---|---|
| Signature getSignature(); | 获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息 |
| Object[] getArgs(); | 获取传入目标方法的参数对象 |
| Object getTarget(); | 获取被代理的对象 |
| Object getThis(); | 获取代理对象 |
ProceedingJoinPoint对象
ProceedingJoinPoint对象是JoinPoint的子接口,该对象只用在@Around的切面方法中,
添加了
Object proceed() throws Throwable //执行目标方法
Object proceed(Object[] var1) throws Throwable //传入的新的参数去执行目标方法
两个方法.
MethodInvocationProceedingJoinPoint 对象
查看源码得知MethodInvocationProceedingJoinPoint是ProceedingJoinPoint和StaticPart的实现,只要使用的还是ProceedingJoinPoint对象的两个实现方法。
参考
结语
欢迎关注微信公众号『码仔zonE』,专注于分享Java、云计算相关内容,包括SpringBoot、SpringCloud、微服务、Docker、Kubernetes、Python等领域相关技术干货,期待与您相遇!

自定义注解-方法重试@RetryProcess的更多相关文章
- java自定义注解注解方法、类、属性等等【转】
http://anole1982.iteye.com/blog/1450421 http://www.open-open.com/doc/view/51fe76de67214563b20b385320 ...
- redis结合自定义注解实现基于方法的注解缓存,及托底缓存的实现
本次分享如何使用redis结合自定义注解实现基于方法的注解缓存,及托底缓存的实现思路 现在的互联网公司大多数都是以Redis作为缓存,使用缓存的优点就不赘述了,写这篇文章的目的就是想帮助同学们如 ...
- Java 扫描实现 Ioc 动态注入,过滤器根据访问url调用自定义注解标记的类及其方法
扫描实现 Ioc 动态注入 参考: http://www.private-blog.com/2017/11/16/java-%e6%89%ab%e6%8f%8f%e5%ae%9e%e7%8e%b0-i ...
- 使用AOP实现方法执行时间和自定义注解
环境:IDEA2018+JDK1.8+SpringBoot 第一步:在pom文件中引入依赖(度娘有很多(*^▽^*)): <!--引入AOP的依赖--><dependency> ...
- springBoot2.0+redis+fastJson+自定义注解实现方法上添加过期时间
springBoot2.0集成redis实例 一.首先引入项目依赖的maven jar包,主要包括 spring-boot-starter-data-redis包,这个再springBoot2.0之前 ...
- 使用Spring自定义注解实现任务路由的方法
在Spring mvc的开发中,我们可以通过RequestMapping来配,当前方法用于处理哪一个URL的请求.同样我们现在有一个需求,有一个任务调度器,可以按照不同的任务类型路由到不同的任务执行器 ...
- java反射机制获取自定义注解值和方法
由于工作需求要应用到java反射机制,就做了一下功能demo想到这些就做了一下记录 这个demo目的是实现动态获取到定时器的方法好注解名称,废话不多说了直接上源码 1.首先需要自定义注解类 /** * ...
- 010-Spring aop 001-核心说明-拦截指定类与方法、基于自定义注解的切面
一.概述 面向切面编程(AOP)是针对面向对象编程(OOP)的补充,可以非侵入式的为多个不具有继承关系的对象引入相同的公共行为例如日志.安全.事务.性能监控等等.SpringAOP允许将公共行为从业务 ...
- Java:深入自定义注解(Annotation)
在网上找了很多资料也有写的比较好的,但是总有有一点半点的细节没有写出来,在这里自己总结下使用. 使用Java的自定义注解,首先个人需要了解下Java为我们提供的元注解和相关定义注解的语法.(这个我在网 ...
随机推荐
- 面经手册 · 第2篇《数据结构,HashCode为什么使用31作为乘数?》
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 在面经手册的前两篇介绍了<面试官都问我啥>和<认知自己的技术栈盲区 ...
- .net+uniapp 前后端数据交互相关问题记录
uniapp 提交form表单 @submit EventHandle 携带 form 中的数据触发 submit 事件,event.detail = {value : {'name': 'value ...
- 【计算机算法设计与分析】——SVM
一.简介 支持向量机(support vector machines)是一种二分类模型,它的目的是寻找一个超平面来对样本进行分割,分割的原则是间隔最大化,最终转化为一个凸二次规划问题来求解.由简至繁的 ...
- [leetcode/lintcode 题解] 有效回文 II · Valid Palindrome II
[题目描述] 给一个非空字符串 s,你最多可以删除一个字符.判断是否可以把它变成回文串. 在线评测地址: https://www.lintcode.com/problem/valid-palindro ...
- JS学习第九天
DOM创建表格: insertRow(index) 在指定索引位置插入一行 deleteRow(index) 删除表格中index索引处的行 insertCell(index) 在index处创建一个 ...
- Vue Vue.use() / Vue.component / router-view
Vue.use Vue.use 的作用是安装插件 Vue.use 接收一个参数 如果这个参数是函数的话,Vue.use 直接调用这个函数注册组件 如果这个参数是对象的话,Vue.use 将调用 ins ...
- iMX283光盘资料 163网盘
[光盘资料]EasyARM-i.MX280A_283A_287A V1.04(EasyARM-i.MX280A_283A_287A_cd).zip 提取码: y6pnW6sY
- 存储系列之 从ext2到ext3、ext4 的变化与区别
引言:ext3 和 ext4 对 ext2 进行了增强,但是其核心设计并没有发生变化.所以建议先查看上上篇的<存储系列之 Linux ext2 概述 >,有了ext2的基础,看这篇就是so ...
- AS报错:gradle project sync failed
情形一: Android studio下突然报错: gradle project sync failed.Basic functionality(e.g.editing,debugging) will ...
- 封装Vue Element的table表格组件
上周分享了几篇关于React组件封装方面的博文,这周就来分享几篇关于Vue组件封装方面的博文,也好让大家能更好地了解React和Vue在组件封装方面的区别. 在封装Vue组件时,我依旧会交叉使用函数式 ...