浅谈spring的重试机制无效@Retryable@EnableRetry

spring-retry模块支持方法和类、接口、枚举级别的重试

方式很简单,引入pom包

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>lastest</version>
</parent>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.retry/spring-retry -->
<dependency>
  <groupId>org.springframework.retry</groupId>
  <artifactId>spring-retry</artifactId>
  <version>1.1.2.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.8.6</version>
</dependency>

然后在@Configuration注解的类中添加@EnableRetry

最后在想要重试的方法上添加@Retryable(Exception.class)

由于retry用到了aspect增强,所有会有aspect的坑,就是方法内部调用,会使aspect增强失效,那么retry当然也会失效。

例如

public class demo {
  public void A() {
    B();
  }

  @Retryable(Exception.class)
  public void B() {
    throw new RuntimeException("retry...");
  }
}

这种情况B()不会重试。

补充知识:Springboot整合Spring Retry实现重试机制

在项目开发过程中,经常会有这样的情况:第一次执行一个操作不成功,考虑到可能是网络原因造成,就多执行几次操作,直到得到想要的结果为止,这就是重试机制。

Springboot可以通过整合Spring Retry框架实现重试。

下面讲一下在之前新建的ibatis项目基础上整合Spring Retry框架的步骤:

1、首先要在pom.xml配置中加入spring-retry的依赖:

<dependency>
  <groupId>org.springframework.retry</groupId>
  <artifactId>spring-retry</artifactId>
</dependency>
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
</dependency>

2、在启动类中加入重试注解@EnableRetry。

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.retry.annotation.EnableRetry;

@EnableRetry //重试注解
@MapperScan("com.batis.mapper")
@SpringBootApplication
public class BatisApplication {
  public static void main(String[] args) {
    SpringApplication.run(BatisApplication.class, args);
  }
}

3、新建重试接口RetryService和实现类RetryServiceImpl

重试接口:

public interface RetryService {
  void retryTransferAccounts(int fromAccountId, int toAccountId, float money) throws Exception;
}

接口实现类:

import com.batis.mapper.AccountMapper;
import com.batis.model.Account;
import com.batis.service.RetryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class RetryServiceImpl implements RetryService {
  @Autowired
  private AccountMapper accountMapper;

  @Transactional
  @Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 3000, multiplier = 1, maxDelay = 10000))
  @Override
  public void retryTransferAccounts(int fromAccountId, int toAccountId, float money) throws Exception {
    Account fromAccount = accountMapper.findOne(fromAccountId);
    fromAccount.setBalance(fromAccount.getBalance() - money);
    accountMapper.update(fromAccount);

    int a = 2 / 0;
    Account toAccount = accountMapper.findOne(toAccountId);
    toAccount.setBalance(toAccount.getBalance() + money);
    accountMapper.update(toAccount);
    throw new Exception();
  }

  @Recover
  public void recover(Exception e) {
    System.out.println("回调方法执行!!!");
  }
}

@Retryable:标记当前方法会使用重试机制

value:重试的触发机制,当遇到Exception异常的时候,会触发重试

maxAttempts:重试次数(包括第一次调用)

delay:重试的间隔时间

multiplier:delay时间的间隔倍数

maxDelay:重试次数之间的最大时间间隔,默认为0,如果小于delay的设置,则默认为30000L

@Recover:标记方法为回调方法,传参与@Retryable的value值需一致

4、新建重试控制器类RetryController

import com.batis.service.RetryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/retry")
public class RetryController {
  @Autowired
  private RetryService retryService;

  @RequestMapping(value = "/transfer", method = RequestMethod.GET)
  public String transferAccounts() {
    try {
      retryService.retryTransferAccounts(1, 2, 200);
      return "ok";
    } catch (Exception e) {
      return "no";
    }
  }
}

5、启动ibatis项目进行测试,在浏览器地址栏输入:http://localhost:8080/retry/transfer

可以看到,转账操作一共执行了3次,最后执行了回调方法。

至此Springboot整合Spring Retry的步骤已经完成,测试也非常成功!

有可以改进的地方希望诸位同学不要吝惜笔墨,加以指正,万分感谢!

以上这篇浅谈spring的重试机制无效@Retryable@EnableRetry就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Spring的异常重试框架Spring Retry简单配置操作

    相关api见:点击进入 /* * Copyright 2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *

  • SpringCloud重试机制配置详解

    首先声明一点,这里的重试并不是报错以后的重试,而是负载均衡客户端发现远程请求实例不可到达后,去重试其他实例. @Bean @LoadBalanced RestTemplate restTemplate() { HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(); httpRequestFactory.setReadTimeout(5000)

  • Spring Cloud重试机制与各组件的重试总结

    SpringCloud重试机制配置 首先声明一点,这里的重试并不是报错以后的重试,而是负载均衡客户端发现远程请求实例不可到达后,去重试其他实例. @Bean @LoadBalanced RestTemplate restTemplate() { HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(); httpRequestFactory.se

  • SpringBoot处理全局统一异常的实现

    在后端发生异常或者是请求出错时,前端通常显示如下 Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback. Fri Jun 07 15:38:07 CST 2019 There was an unexpected error (type=Not Found, status=404). No message available 对于

  • 浅谈spring的重试机制无效@Retryable@EnableRetry

    spring-retry模块支持方法和类.接口.枚举级别的重试 方式很简单,引入pom包 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>lastest</version> </parent> <dependency> &

  • 浅谈spring中isolation和propagation的用法

    可以在XML文件中进行配置,下面的代码是个示意代码 <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED" isolation="READ_COMMITTED"/>增加记录的方法 <t

  • 浅谈Spring的两种事务定义方式

    一.声明式 这种方法不需要对原有的业务做任何修改,通过在XML文件中定义需要拦截方法的匹配即可完成配置,要求是,业务处理中的方法的命名要有规律,比如setXxx,xxxUpdate等等.详细配置如下: <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="

  • 浅谈Spring的两种配置容器

    Spring提供了两种容器类型 SpringIOC容器是一个IOC Service Provider.提供了两种容器类型:BeanFactory和ApplicationContext.Spring的IOC容器是一个提供IOC支持的轻量级容器.除了基本的ioc支持,它作为轻量级容器还提供了IOC之外的支持. BeanFactory BeanFactory是基础类型IOC容器.顾名思义,就是生产Bean的工厂.能够提供完整的IOC服务.没有特殊指定的话,其默认采用延迟初始化策略.只有当客户端对象需要

  • 浅谈SpringBoot之事务处理机制

    一.Spring的事务机制 所有的数据访问技术都有事务处理机制,这些技术提供了API用来开启事务.提交事务来完成数据操作,或者在发生错误的时候回滚数据. 而Spring的事务机制是用统一的机制来处理不同数据访问技术的事务处理.Spring的事务机制提供了一个PlatformTransactionManager接口,不同的数据访问技术的事务使用不同的接口实现: 在程序中定义事务管理器的代码如下: @Bean public PlatformTransactionManager transaction

  • 浅谈Spring Session工作原理

    目录 1.引入背景 2.使用方法 3.工作流程 4.缓存机制 5.事件订阅 6.总结 1.引入背景 HTTP协议本身是无状态的,为了保存会话信息,浏览器Cookie通过SessionID标识会话请求,服务器以SessionID为key来存储会话信息.在单实例应用中,可以考虑应用进程自身存储,随着应用体量的增长,需要横向扩容,多实例session共享问题随之而来. 应用部署在Tomcat时,session是由Tomcat内存维护,如果应用部署多个实例,session就不能共享.Spring Ses

  • 浅谈Spring 中 @EnableXXX 注解的套路

    目录 前言 设计目标 @EnableScheduling (导入一个 @Configuration 类) @EnableTransactionManagement(导入一个 ImportSelector) @EnableAspectJAutoProxy (在 Bean 定义层导入) 结论 前言 在 Spring 框架中有很多实用的功能,不需要写大量的配置代码,只需添加几个注解即可开启. 其中一个重要原因是那些 @EnableXXX 注解,它可以让你通过在配置类加上简单的注解来快速地开启诸如事务管

  • 浅谈spring容器中bean的初始化

    当我们在spring容器中添加一个bean时,如果没有指明它的scope属性,则默认是singleton,也就是单例的. 例如先声明一个bean: public class People { private String name; private String sex; public String getName() { return name; } public void setName(String name) { this.name = name; } public String get

  • 浅谈spring中用到的设计模式及应用场景

    1.工厂模式,在各种BeanFactory以及ApplicationContext创建中都用到了 2.模版模式,在各种BeanFactory以及ApplicationContext实现中也都用到了 3.代理模式,Spring AOP 利用了 AspectJ AOP实现的! AspectJ AOP 的底层用了动态代理 动态代理有两种 目标方法有接口时候自动选用 JDK 动态代理 目标方法没有接口时候选择 CGLib 动态代理 4.策略模式,加载资源文件的方式,使用了不同的方法,比如:ClassPa

  • 浅谈spring中的default-lazy-init参数和lazy-init

    在spring的配置中的根节点上有个  default-lazy-init="true"配置: 1.spring的default-lazy-init参数 此参数表示延时加载,即在项目启动时不会实例化注解的bean,除非启动项目时需要用到,未实例化的注解对象在程序实际访问调用时才注入调用 spring在启动的时候,default-lazy-init参数默认为false,会默认加载整个对象实例图,从初始化ACTION配置.到 service配置到dao配置.乃至到数据库连接.事务等等.这样

随机推荐