Override retry listeners for each Retryable method

This commit is contained in:
maciekwiso
2017-03-08 23:19:05 +01:00
committed by Dave Syer
parent b4f076c258
commit 68d66033b1
4 changed files with 91 additions and 11 deletions

View File

@@ -93,7 +93,7 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn
private BeanFactory beanFactory;
private RetryListener[] listeners;
private RetryListener[] defaultListeners;
/**
* @param sleeper the sleeper to set
@@ -127,12 +127,12 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn
/**
* Retry listeners to apply to all operations.
* @param listeners the listeners
* @param defaultListeners the listeners
*/
public void setListeners(Collection<RetryListener> listeners) {
ArrayList<RetryListener> retryListeners = new ArrayList<RetryListener>(listeners);
public void setDefaultListeners(Collection<RetryListener> defaultListeners) {
ArrayList<RetryListener> retryListeners = new ArrayList<RetryListener>(defaultListeners);
AnnotationAwareOrderComparator.sort(retryListeners);
this.listeners = retryListeners.toArray(new RetryListener[0]);
this.defaultListeners = retryListeners.toArray(new RetryListener[0]);
}
@Override
@@ -208,7 +208,7 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn
}
private MethodInterceptor getStatelessInterceptor(Object target, Method method, Retryable retryable) {
RetryTemplate template = createTemplate();
RetryTemplate template = createTemplate(retryable.listeners());
template.setRetryPolicy(getRetryPolicy(retryable));
template.setBackOffPolicy(getBackoffPolicy(retryable.backoff()));
return RetryInterceptorBuilder.stateless()
@@ -219,7 +219,7 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn
}
private MethodInterceptor getStatefulInterceptor(Object target, Method method, Retryable retryable) {
RetryTemplate template = createTemplate();
RetryTemplate template = createTemplate(retryable.listeners());
template.setRetryContextCache(this.retryContextCache);
CircuitBreaker circuit = AnnotationUtils.findAnnotation(method, CircuitBreaker.class);
@@ -254,14 +254,24 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn
.build();
}
private RetryTemplate createTemplate() {
private RetryTemplate createTemplate(String[] listenersBeanNames) {
RetryTemplate template = new RetryTemplate();
if (listeners!=null) {
template.setListeners(listeners);
if (listenersBeanNames.length > 0) {
template.setListeners(getListenersBeans(listenersBeanNames));
} else if (defaultListeners !=null) {
template.setListeners(defaultListeners);
}
return template;
}
private RetryListener[] getListenersBeans(String[] listenersBeanNames) {
RetryListener[] listeners = new RetryListener[listenersBeanNames.length];
for (int i = 0; i < listeners.length; i++) {
listeners[i] = beanFactory.getBean(listenersBeanNames[i], RetryListener.class);
}
return listeners;
}
private MethodInvocationRecoverer<?> getRecoverer(Object target, Method method) {
if (target instanceof MethodInvocationRecoverer) {
return (MethodInvocationRecoverer<?>) target;

View File

@@ -134,7 +134,7 @@ public class RetryConfiguration extends AbstractPointcutAdvisor implements Intro
interceptor.setRetryContextCache(retryContextCache);
}
if (retryListeners != null) {
interceptor.setListeners(retryListeners);
interceptor.setDefaultListeners(retryListeners);
}
if (methodArgumentsKeyGenerator != null) {
interceptor.setKeyGenerator(methodArgumentsKeyGenerator);

View File

@@ -118,4 +118,10 @@ public @interface Retryable {
*/
String exceptionExpression() default "";
/**
* Bean names of retry listeners to use instead of default ones defined in Spring context
* @return retry listeners bean names
*/
String[] listeners() default {};
}

View File

@@ -43,6 +43,17 @@ public class EnableRetryWithListenersTests {
context.close();
}
@Test
public void overrideListener() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
TestConfigurationMultipleListeners.class);
ServiceWithOverriddenListener service = context.getBean(ServiceWithOverriddenListener.class);
service.service();
assertEquals(1, context.getBean(TestConfigurationMultipleListeners.class).count1);
assertEquals(0, context.getBean(TestConfigurationMultipleListeners.class).count2);
context.close();
}
@Configuration
@EnableRetry(proxyTargetClass = true)
protected static class TestConfiguration {
@@ -67,6 +78,42 @@ public class EnableRetryWithListenersTests {
}
@Configuration
@EnableRetry(proxyTargetClass = true)
protected static class TestConfigurationMultipleListeners {
private int count1 = 0;
private int count2 = 0;
@Bean
public ServiceWithOverriddenListener service() {
return new ServiceWithOverriddenListener();
}
@Bean
public RetryListener listener1() {
return new RetryListenerSupport() {
@Override
public <T, E extends Throwable> void close(RetryContext context,
RetryCallback<T, E> callback, Throwable throwable) {
count1++;
}
};
}
@Bean
public RetryListener listener2() {
return new RetryListenerSupport() {
@Override
public <T, E extends Throwable> void close(RetryContext context,
RetryCallback<T, E> callback, Throwable throwable) {
count2++;
}
};
}
}
protected static class Service {
private int count = 0;
@@ -84,4 +131,21 @@ public class EnableRetryWithListenersTests {
}
protected static class ServiceWithOverriddenListener {
private int count = 0;
@Retryable(backoff = @Backoff(delay = 1000), listeners = "listener1")
public void service() {
if (count++ < 2) {
throw new RuntimeException("Planned");
}
}
public int getCount() {
return count;
}
}
}