如何在MethodInvocationRetryListenerSupport中获取类级@Retryable的label?
解决Spring Retry类级别@Retryable的label获取问题
问题原因
当使用**自定义RetryOperationsInterceptor**时,类级别@Retryable注解的label属性不会自动传递到MethodInvocationRetryCallback中,默认情况下getLabel()返回的是方法签名,而非注解配置的label值。
解决方案
通过MethodInvocationRetryCallback获取目标方法所在的类,再通过反射读取类级别(或方法级别)的@Retryable注解中的label值。修改GrpcClientRetryListener的相关方法如下:
@Slf4j @Component public class GrpcClientRetryListener extends MethodInvocationRetryListenerSupport { @Override public <T, E extends Throwable> void onSuccess( RetryContext context, RetryCallback<T, E> callback, T result) { if (callback instanceof MethodInvocationRetryCallback<T, E> methodInvocationRetryCallback) { log.info( "重试成功: {}, 重试次数: {}", getRetryLabel(methodInvocationRetryCallback), context.getRetryCount()); } super.onSuccess(context, callback, result); } @Override public <T, E extends Throwable> void onError( RetryContext context, RetryCallback<T, E> callback, Throwable throwable) { if (callback instanceof MethodInvocationRetryCallback<T, E> methodInvocationRetryCallback) { log.info( "重试失败: {}, 重试次数: {}", getRetryLabel(methodInvocationRetryCallback), context.getRetryCount()); } super.onError(context, callback, throwable); } private <T, E extends Throwable> String getRetryLabel( MethodInvocationRetryCallback<T, E> methodInvocationRetryCallback) { MethodInvocation invocation = methodInvocationRetryCallback.getInvocation(); // 获取目标类实例的Class对象 Class<?> targetClass = invocation.getThis().getClass(); // 优先读取方法上的@Retryable注解label Retryable methodRetryable = invocation.getMethod().getAnnotation(Retryable.class); if (methodRetryable != null && !StringUtils.isEmpty(methodRetryable.label())) { return methodRetryable.label(); } // 读取类上的@Retryable注解label(处理代理类场景) Retryable classRetryable = AnnotationUtils.findAnnotation(targetClass, Retryable.class); if (classRetryable != null && !StringUtils.isEmpty(classRetryable.label())) { return classRetryable.label(); } // 无配置时返回方法签名作为兜底 return methodInvocationRetryCallback.getLabel(); } }
关键说明
- 使用
AnnotationUtils.findAnnotation而非直接targetClass.getAnnotation(),确保能正确获取代理类背后的真实类上的注解。 - 遵循Spring Retry的注解优先级:方法级别注解优先于类级别注解,如果方法上配置了
@Retryable,优先读取方法的label值。 - 保留方法签名作为兜底逻辑,避免无注解场景下出现空值。
额外注意
无需修改GrpcClientRetryConfig中的拦截器配置,当前方案通过反射直接读取注解属性,不依赖拦截器的参数传递逻辑。
内容的提问来源于stack exchange,提问作者tuk
相关产品推荐
相关产品推荐

