我有一个具有以下定义的方法
@Retryable(value = {
APICallFailedException.class,
IOException.class}, maxAttempts = TransformerConstants.GET_API_MAX_ATTEMPTS, backoff = @Backoff(delay = TransformerConstants.DELAY))
public <T> T getAPIResponse(String url, Class<T> classType)
其中 APICallFailedException.class 扩展了运行时异常类
我有一个恢复方法,当所有重试尝试失败时都会调用该方法。它有以下定义
@Recover
public <T> T getBackendResponseFallback(RuntimeException exception, String getAPIURL,
Class<T> classType)
我通过在末尾添加一个 String 参数来更改这两个方法的方法定义,所以现在它们看起来像
@Retryable(value = {
APICallFailedException.class,
IOException.class}, maxAttempts = TransformerConstants.GET_API_MAX_ATTEMPTS, backoff = @Backoff(delay = TransformerConstants.DELAY))
public <T> T getAPIResponse(String url, Class<T> classType, **String APIUrl**)
@Recover
public <T> T getBackendResponseFallback(RuntimeException exception, String getAPIURL,
Class<T> classType, **String apiURL**)
执行此操作后,当可重试方法失败并调用recover时,会抛出参数不匹配异常
下面是堆栈跟踪
Caused by: java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:282)
at org.springframework.retry.annotation.RecoverAnnotationRecoveryHandler.recover(RecoverAnnotationRecoveryHandler.java:73)
at org.springframework.retry.interceptor.RetryOperationsInterceptor$ItemRecovererCallback.recover(RetryOperationsInterceptor.java:141)
at org.springframework.retry.support.RetryTemplate.handleRetryExhausted(RetryTemplate.java:512)
at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:351)
at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:180)
at org.springframework.retry.interceptor.RetryOperationsInterceptor.invoke(RetryOperationsInterceptor.java:115)
at org.springframework.retry.annotation.AnnotationAwareRetryOperationsInterceptor.invoke(AnnotationAwareRetryOperationsInterceptor.java:153)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
at com.kroger.cxp.app.transformer.util.RestClientUtil$$EnhancerBySpringCGLIB$$6079045e.getAPIResponse(<generated>)
我想了解为什么会发生这种情况。 Spring doc在@Recover中说最佳匹配方法是根据第一个参数的类型和正在处理的异常的类型来选择的。选择类层次结构中最接近的匹配,因此,例如,如果正在处理 IllegalArgumentException 并且有一个第一个参数是 RuntimeException 的方法,那么它将优先于第一个参数是 Throwable 的方法
getAPIResponse 方法调用其内部的另一个方法并定义
private HttpResponse<byte[]> callAPI(OkHttpClient okHttpClient, String url, Request request)
是否有可能在 Recover 方法参数中添加字符串参数后,它会尝试与第二个 API 调用匹配,即 callAPI 而不是预期的 getAPIResponse
最佳答案
用你的代码对我来说效果很好;您能提供更多详细信息吗?
@SpringBootApplication
@EnableRetry
public class So68724467Application {
public static void main(String[] args) {
SpringApplication.run(So68724467Application.class, args);
}
@Bean
public ApplicationRunner runner(Foo foo) {
return args -> {
System.out.println(foo.getAPIResponse("foo", Object.class, "bar"));
};
}
}
@Component
class Foo {
@Retryable(value = {
IllegalStateException.class,
IOException.class }, maxAttempts = 3, backoff = @Backoff(delay = 2000))
public <T> T getAPIResponse(String url, Class<T> classType, String APIUrl) {
System.out.println("Retryable");
throw new IllegalStateException("test");
}
@Recover
public <T> T getBackendResponseFallback(RuntimeException exception, String getAPIURL,
Class<T> classType, String apiUR) {
System.out.println("Recover");
return (T) new Object();
}
}
关于spring - 获取 @Recover 注释的参数类型不匹配错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68724467/