Springboot @retryable没有重试

eng*_*ngg 10 java spring maven spring-retry spring-boot

以下代码未重试.我错过了什么?

@EnableRetry
@SpringBootApplication
public class App implements CommandLineRunner
{
    .........
    .........


    @Retryable()
    ResponseEntity<String> authenticate(RestTemplate restTemplate, HttpEntity<MultiValueMap<String, String>> entity) throws Exception
    {
        System.out.println("try!");
        throw new Exception();
        //return restTemplate.exchange(auth_endpoint, HttpMethod.POST, entity, String.class);
    }
Run Code Online (Sandbox Code Playgroud)

我已将以下内容添加到pom.xml中.

    <dependency>
        <groupId>org.springframework.retry</groupId>
        <artifactId>spring-retry</artifactId>
        <version>1.1.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
Run Code Online (Sandbox Code Playgroud)

我也试过为@Retryable提供不同的参数组合.

@Retryable(maxAttempts=10,value=Exception.class,backoff=@Backoff(delay = 2000,multiplier=2))
Run Code Online (Sandbox Code Playgroud)

谢谢.

Ken*_*ger 20

Spring的@Retryable、@Cacheable、@Transaction等都是使用面向切面编程实现的。Spring通过基于代理的编织来实现AOP。代理拦截从一个 bean 到另一个 bean 的调用。代理无法拦截从一个对象的方法到另一个对象的方法的调用。这是基于代理的编织的一般限制。

以下解决方案解决了这个限制:1)如上所述,使用@Autowired(或@Resource)注入带有自引用的bean;对此引用的调用会通过代理。2)使用AspectJ的ClassLoader而不是Spring默认的基于代理的编织。3) 如上所述,将方法放在单独的 bean 上。我在不同的情况下做过每一种,每种都有优点和缺点。


nkh*_*che 10

在Spring boot 2.0.2 Release中,我发现如果你在同一个类中有可重试和调用的方法,则@Retryable不起作用.在调试时发现切入点没有正确构建.目前,此问题的解决方法是我们需要在不同的类中编写该方法并调用它.

可在此处找到工作示例.

  • 这是因为 Spring 创建了一个 Proxy 对象来处理重试,而它无法创建自己的代理对象。使用其他注释作为“@Transactional”时也会出现同样的问题 (5认同)
  • 这就是所有 Spring 注释的工作方式。您需要一个单独的代理对象来使排序能够应用附加逻辑。 (4认同)
  • 观察到与 spring boot 2.0.0 到 2.0.5 相同的情况。检查 mvn repo:2017 年之后没有 spring-retry 版本,而 spring boot 2 2018 年到货。有没有人设法使 spring-retry 与任何版本的 spring-boot 2.x 一起工作?同时回滚到 spring boot 1.5.15,它工作正常 (2认同)
  • 这就是Spring代理的工作方式。 (2认同)

Use*_*F40 9

对于@Retryable要发现的方法的注释,需要从初始化的上下文中正确调用它.方法是从spring上下文中调用bean还是通过其他方式调用?

如果测试这是你的跑步者使用SpringJunit4ClassRunner

  • 这应该是公认的答案,当你说"我发现如果从你试图重试的方法返回一些内容时,那么@Retryable()就不起作用了." 是错误的,你可以在retry方法中实际返回一个对象,重点是需要从bean调用该方法. (3认同)

MyT*_*nts 6

对于那些想@Retryable在同一个类中调用块的人可以这样。

这里的关键是不要直接调用方法,而是通过自注入的bean

@Slf4j
@Service
public class RetryService {

    @Resource(name = "retryService")
    private RetryService self;

    public String getValue(String appender) {
        return self.getData(appender);
    }

    @Retryable(value = NumberFormatException.class, maxAttempts = 4, backoff = @Backoff(500))
    public String getData(String appender) {
        log.info("Calling getData");
        Integer value = Integer.parseInt(appender);
        value++;
        return value.toString();
    }

    @Recover
    public String recoverData(String appender) {
        log.info("Calling recoverData");
        return "DEFAULT";
    }

}
Run Code Online (Sandbox Code Playgroud)

可以在此处阅读有关使用重试的详细信息


wah*_*cse 5

我解决了 我发现,如果从尝试重试的方法返回某些内容,则@Retryable()无法正常工作。

pom.xml中的Maven依赖项

    <dependency>
        <groupId>org.springframework.retry</groupId>
        <artifactId>spring-retry</artifactId>
        <version>1.1.5.RELEASE</version>
    </dependency>
Run Code Online (Sandbox Code Playgroud)

春季启动Application.java

@SpringBootApplication
@EnableTransactionManagement
@EnableRetry
public class Application {

     public static void main(String[] args) throws Exception {
       SpringApplication.run(Application.class, args);
     }

}
Run Code Online (Sandbox Code Playgroud)

在controller.java中

@RestController
public class JavaAllDataTypeController {

@Autowired
JavaAllDataTypeService JavaAllDataTypeService;


@RequestMapping(
        value = "/springReTryTest",
        method = RequestMethod.GET
)
public ResponseEntity<String> springReTryTest() {

    System.out.println("springReTryTest controller");

    try {
         JavaAllDataTypeService.springReTryTest();
    } catch (Exception e) {
        e.printStackTrace();
    }

    return new  ResponseEntity<String>("abcd", HttpStatus.OK);
  }

}
Run Code Online (Sandbox Code Playgroud)

在service.java中

@Service
@Transactional
public class JavaAllDataTypeService {

 // try the method 9 times with 2 seconds delay.
 @Retryable(maxAttempts=9,value=Exception.class,backoff=@Backoff(delay = 2000))
 public void springReTryTest() throws Exception {

    System.out.println("try!");
    throw new Exception();
  }

}
Run Code Online (Sandbox Code Playgroud)

输出:尝试9次然后抛出异常。

在此处输入图片说明


小智 5

我遇到了与原始问题中描述的完全相同的问题。

就我而言,事实证明该spring-boot-starter-aop依赖项被意外地未包含在内。将其添加到 my 后pom.xml,我的@Retryable方法按预期工作。

从方法返回值@Retryable对我来说效果很好。