diff --git a/src/main/java/org/springframework/retry/annotation/AnnotationAwareRetryOperationsInterceptor.java b/src/main/java/org/springframework/retry/annotation/AnnotationAwareRetryOperationsInterceptor.java index c4cbde5..2f906de 100644 --- a/src/main/java/org/springframework/retry/annotation/AnnotationAwareRetryOperationsInterceptor.java +++ b/src/main/java/org/springframework/retry/annotation/AnnotationAwareRetryOperationsInterceptor.java @@ -75,6 +75,7 @@ import org.springframework.util.StringUtils; * @author Dave Syer * @author Artem Bilan * @author Gary Russell + * @author Roman Akentev * @since 1.1 */ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionInterceptor, BeanFactoryAware { @@ -323,6 +324,9 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn } private RetryListener[] getListenersBeans(String[] listenersBeanNames) { + if (listenersBeanNames.length == 1 && "".equals(listenersBeanNames[0].trim())) { + return new RetryListener[0]; + } RetryListener[] listeners = new RetryListener[listenersBeanNames.length]; for (int i = 0; i < listeners.length; i++) { listeners[i] = this.beanFactory.getBean(listenersBeanNames[i], RetryListener.class); diff --git a/src/main/java/org/springframework/retry/annotation/Retryable.java b/src/main/java/org/springframework/retry/annotation/Retryable.java index d148f7c..d470b8c 100644 --- a/src/main/java/org/springframework/retry/annotation/Retryable.java +++ b/src/main/java/org/springframework/retry/annotation/Retryable.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2022 the original author or authors. + * Copyright 2014-2023 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. @@ -31,6 +31,7 @@ import org.springframework.core.annotation.AliasFor; * @author Artem Bilan * @author Gary Russell * @author Maksim Kita + * @author Roman Akentev * @since 1.1 * */ @@ -165,7 +166,9 @@ public @interface Retryable { /** * Bean names of retry listeners to use instead of default ones defined in Spring - * context + * context. If this attribute is set to an empty string {@code ""}, it will + * effectively exclude all retry listeners, including with the default listener beans, + * from being used. * @return retry listeners bean names */ String[] listeners() default {}; diff --git a/src/test/java/org/springframework/retry/annotation/EnableRetryWithListenersTests.java b/src/test/java/org/springframework/retry/annotation/EnableRetryWithListenersTests.java index aeccb68..39ddfd2 100644 --- a/src/test/java/org/springframework/retry/annotation/EnableRetryWithListenersTests.java +++ b/src/test/java/org/springframework/retry/annotation/EnableRetryWithListenersTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2023 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. @@ -31,6 +31,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Dave Syer * @author Gary Russell * @author Henning Pƶttker + * @author Roman Akentev * */ public class EnableRetryWithListenersTests { @@ -55,6 +56,16 @@ public class EnableRetryWithListenersTests { context.close(); } + @Test + public void excludedListeners() { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( + TestConfigurationExcludedListeners.class); + ServiceWithExcludedListeners service = context.getBean(ServiceWithExcludedListeners.class); + service.service(); + assertThat(context.getBean(TestConfigurationExcludedListeners.class).count).isEqualTo(0); + context.close(); + } + @Configuration @EnableRetry(proxyTargetClass = true) protected static class TestConfiguration { @@ -116,6 +127,41 @@ public class EnableRetryWithListenersTests { } + @Configuration + @EnableRetry(proxyTargetClass = true) + protected static class TestConfigurationExcludedListeners { + + private int count = 0; + + @Bean + public ServiceWithExcludedListeners service() { + return new ServiceWithExcludedListeners(); + } + + @Bean + public RetryListener listener1() { + return new RetryListener() { + @Override + public void close(RetryContext context, RetryCallback callback, + Throwable throwable) { + count++; + } + }; + } + + @Bean + public RetryListener listener2() { + return new RetryListener() { + @Override + public void close(RetryContext context, RetryCallback callback, + Throwable throwable) { + count++; + } + }; + } + + } + protected static class Service { private int count = 0; @@ -150,4 +196,21 @@ public class EnableRetryWithListenersTests { } + protected static class ServiceWithExcludedListeners { + + private int count = 0; + + @Retryable(backoff = @Backoff(delay = 1000), listeners = "") + public void service() { + if (count++ < 2) { + throw new RuntimeException("Planned"); + } + } + + public int getCount() { + return count; + } + + } + }