自定义重试标注

因为有很多重试场景,每次都是我们硬编,也没有找到现成的重试方案,因此写了一个重试标注。

优点:用法很简单,只需在需要重试的方法加上标注,并指定重试次数。把spring-repeater.xml引入即可。由于它重试的条件是方法发生异常,因此需要被重试的方法必需在发生异常且需重试时将异常抛出来。如果代码够规范这不应该是问题。
例如需要对updateInfoToDb方法进行异常后重试3次(实际最多只重试2次,最多共执行3次)
@Repeater(3)
public String updateInfoToDb(String id) throws Throwable {
if("1".equals(id)){
throw new MyException();
}else if("2".equals(id)){
throw new RuntimeException("id:"+ id);
}
return "id:" + id;
}
缺点:做了一个性能测试,对于加上重试标注的方法比原生方法的执行效率会慢10倍。因此大家需要慎重考虑使用场景。

定义重试annotation

package com.jd.test.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Repeater {
	/**
	 * 重试次数
	 * @return 
	 */
	int value() default 3 ; 
	//Class<? extends Throwable>[] exception();
	
}


定义切面

package com.jd.test.service;

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.springframework.stereotype.Component;

import com.jd.test.annotation.Repeater;

/**
 * 定义重试切面
 * 
 * @author pengxiantie
 */
@Aspect
@Component
public class RepeaterPointcut {

	// com.jd.test.service包及子包所有类
	// @Pointcut("execution(* com.jd.test.service.*.* (. .))")
	// RepeaterBusinessImpl 及子包所有类
	// @Pointcut("execution(* com.jd.test.service.impl.RepeaterBusinessImpl.*(..))")
	// 实现RepeaterAware接口的目标类
	// @Pointcut("this (com.jd.test.service.RepeaterAware)") //
	// @Pointcut("execution(* com.jd.test.service.impl.FeeBusinessImpl.*(..))")

	/**
	 * 定义一个切入点。指定所有标注@Repeater的方法。
	 */
	@SuppressWarnings("unused")
	@Pointcut("@annotation(com.jd.test.annotation.Repeater)")
	private void repeaterMethod() {
	}

	/**
	 * 定义环绕通知。 @Around("anyMethod() && @annotation(repeater)"),表示任意方法且带@annotation的方法
	 * 
	 * @param invocation
	 * @param repeater
	 * @return
	 * @throws Throwable
	 */
	@Around("repeaterMethod() && @annotation(repeater)")
	public Object doBasicProfiling(ProceedingJoinPoint invocation, Repeater repeater) throws Throwable {

		int repeatCount = repeater.value();
		if(repeatCount<=0){
			repeatCount = 1;
		}
		
		Throwable exception = null;
		//如果失败,则重试。
		for (int i = 0; i <= repeatCount; i++) {
			try {
				return invocation.proceed();
			} catch (Throwable e) {
				exception = e;
			}
		}
		//重试后仍没有执行成功,抛出异常
		throw exception;
	}

}


spring-repeater.xml  打开aop功能


<?xml version="1.0" encoding="UTF-8"?>
<beans 
	xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:aop="http://www.springframework.org/schema/aop" 
	xsi:schemaLocation="
	http://www.springframework.org/schema/beans   
    http://www.springframework.org/schema/beans/spring-beans.xsd 
    http://www.springframework.org/schema/aop 
	http://www.springframework.org/schema/aop/spring-aop.xsd 
	"
	>
	
	<!-- 打开apo功能 -->
	<aop:aspectj-autoproxy/>

</beans>



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值