From 62d7bfefb6ebd444219afec8f8bc5d833936a32e Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 19 Oct 2020 09:40:42 +0100 Subject: [PATCH] Non-reflective lazy initialization in @RetryConfiguration --- .../retry/annotation/RetryConfiguration.java | 50 ++++++++++++++----- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/springframework/retry/annotation/RetryConfiguration.java b/src/main/java/org/springframework/retry/annotation/RetryConfiguration.java index cc746e3..a878ea4 100644 --- a/src/main/java/org/springframework/retry/annotation/RetryConfiguration.java +++ b/src/main/java/org/springframework/retry/annotation/RetryConfiguration.java @@ -18,13 +18,12 @@ package org.springframework.retry.annotation; import java.lang.annotation.Annotation; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; -import javax.annotation.PostConstruct; - import org.aopalliance.aop.Advice; import org.springframework.aop.ClassFilter; import org.springframework.aop.IntroductionAdvisor; @@ -37,17 +36,21 @@ import org.springframework.aop.support.annotation.AnnotationClassFilter; import org.springframework.aop.support.annotation.AnnotationMethodMatcher; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Configuration; +import org.springframework.core.OrderComparator; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.retry.RetryListener; import org.springframework.retry.backoff.Sleeper; import org.springframework.retry.interceptor.MethodArgumentsKeyGenerator; import org.springframework.retry.interceptor.NewMethodArgumentsIdentifier; import org.springframework.retry.policy.RetryContextCache; +import org.springframework.stereotype.Component; import org.springframework.util.ObjectUtils; import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils.MethodCallback; +import org.springframework.util.comparator.ComparableComparator; /** * Basic configuration for @Retryable processing. For stateful retry, if @@ -61,32 +64,33 @@ import org.springframework.util.ReflectionUtils.MethodCallback; * */ @SuppressWarnings("serial") -@Configuration -public class RetryConfiguration extends AbstractPointcutAdvisor implements IntroductionAdvisor, BeanFactoryAware { +@Component +public class RetryConfiguration extends AbstractPointcutAdvisor + implements IntroductionAdvisor, BeanFactoryAware, InitializingBean { private Advice advice; private Pointcut pointcut; - @Autowired(required = false) private RetryContextCache retryContextCache; - @Autowired(required = false) private List retryListeners; - @Autowired(required = false) private MethodArgumentsKeyGenerator methodArgumentsKeyGenerator; - @Autowired(required = false) private NewMethodArgumentsIdentifier newMethodArgumentsIdentifier; - @Autowired(required = false) private Sleeper sleeper; private BeanFactory beanFactory; - @PostConstruct - public void init() { + @Override + public void afterPropertiesSet() throws Exception { + retryContextCache = findBean(RetryContextCache.class); + methodArgumentsKeyGenerator = findBean(MethodArgumentsKeyGenerator.class); + newMethodArgumentsIdentifier = findBean(NewMethodArgumentsIdentifier.class); + retryListeners = findBeans(RetryListener.class); + sleeper = findBean(Sleeper.class); Set> retryableAnnotationTypes = new LinkedHashSet>(1); retryableAnnotationTypes.add(Retryable.class); this.pointcut = buildPointcut(retryableAnnotationTypes); @@ -96,6 +100,28 @@ public class RetryConfiguration extends AbstractPointcutAdvisor implements Intro } } + private List findBeans(Class type) { + if (beanFactory instanceof ListableBeanFactory) { + ListableBeanFactory listable = (ListableBeanFactory) beanFactory; + if (listable.getBeanNamesForType(type).length == 1) { + ArrayList list = new ArrayList(listable.getBeansOfType(type).values()); + OrderComparator.sort(list); + return list; + } + } + return null; + } + + private T findBean(Class type) { + if (beanFactory instanceof ListableBeanFactory) { + ListableBeanFactory listable = (ListableBeanFactory) beanFactory; + if (listable.getBeanNamesForType(type).length == 1) { + return listable.getBean(type); + } + } + return null; + } + /** * Set the {@code BeanFactory} to be used when looking up executors by qualifier. */