@@ -298,6 +298,8 @@ public void service3() {
|
||||
|
||||
These use the familier Spring SpEL expression syntax (`#{...}`).
|
||||
|
||||
Expressions can contain property placeholders such as `#{${max.delay}}` or `#{@exceptionChecker.${retry.method}(#root)}`
|
||||
|
||||
- `exceptionExpression` is evaluated against the thrown exception as the `#root` object.
|
||||
- `maxAttemptsExpression` and the `@BackOff` expression attributes are evaluated once, during initialization; there is no root object for the evaluation but they can reference other beans in the context.
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.springframework.aop.IntroductionInterceptor;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.expression.BeanFactoryResolver;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
@@ -288,11 +289,11 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn
|
||||
Integer maxAttempts = (Integer) attrs.get("maxAttempts");
|
||||
String maxAttemptsExpression = (String) attrs.get("maxAttemptsExpression");
|
||||
if (StringUtils.hasText(maxAttemptsExpression)) {
|
||||
maxAttempts = PARSER.parseExpression(maxAttemptsExpression, PARSER_CONTEXT).getValue(this.evaluationContext,
|
||||
Integer.class);
|
||||
maxAttempts = PARSER.parseExpression(resolve(maxAttemptsExpression), PARSER_CONTEXT)
|
||||
.getValue(this.evaluationContext, Integer.class);
|
||||
}
|
||||
if (includes.length == 0 && excludes.length == 0) {
|
||||
SimpleRetryPolicy simple = hasExpression ? new ExpressionRetryPolicy(exceptionExpression)
|
||||
SimpleRetryPolicy simple = hasExpression ? new ExpressionRetryPolicy(resolve(exceptionExpression))
|
||||
.withBeanFactory(this.beanFactory)
|
||||
: new SimpleRetryPolicy();
|
||||
simple.setMaxAttempts(maxAttempts);
|
||||
@@ -317,17 +318,17 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn
|
||||
private BackOffPolicy getBackoffPolicy(Backoff backoff) {
|
||||
long min = backoff.delay() == 0 ? backoff.value() : backoff.delay();
|
||||
if (StringUtils.hasText(backoff.delayExpression())) {
|
||||
min = PARSER.parseExpression(backoff.delayExpression(), PARSER_CONTEXT).getValue(this.evaluationContext,
|
||||
Long.class);
|
||||
min = PARSER.parseExpression(resolve(backoff.delayExpression()), PARSER_CONTEXT)
|
||||
.getValue(this.evaluationContext, Long.class);
|
||||
}
|
||||
long max = backoff.maxDelay();
|
||||
if (StringUtils.hasText(backoff.maxDelayExpression())) {
|
||||
max = PARSER.parseExpression(backoff.maxDelayExpression(), PARSER_CONTEXT).getValue(this.evaluationContext,
|
||||
Long.class);
|
||||
max = PARSER.parseExpression(resolve(backoff.maxDelayExpression()), PARSER_CONTEXT)
|
||||
.getValue(this.evaluationContext, Long.class);
|
||||
}
|
||||
double multiplier = backoff.multiplier();
|
||||
if (StringUtils.hasText(backoff.multiplierExpression())) {
|
||||
multiplier = PARSER.parseExpression(backoff.multiplierExpression(), PARSER_CONTEXT)
|
||||
multiplier = PARSER.parseExpression(resolve(backoff.multiplierExpression()), PARSER_CONTEXT)
|
||||
.getValue(this.evaluationContext, Double.class);
|
||||
}
|
||||
if (multiplier > 0) {
|
||||
@@ -360,4 +361,16 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn
|
||||
return policy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the specified value if possible.
|
||||
*
|
||||
* @see ConfigurableBeanFactory#resolveEmbeddedValue
|
||||
*/
|
||||
private String resolve(String value) {
|
||||
if (this.beanFactory != null && this.beanFactory instanceof ConfigurableBeanFactory) {
|
||||
return ((ConfigurableBeanFactory) this.beanFactory).resolveEmbeddedValue(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import static org.junit.Assert.fail;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.junit.Test;
|
||||
@@ -33,6 +34,7 @@ import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
import org.springframework.retry.backoff.ExponentialBackOffPolicy;
|
||||
import org.springframework.retry.backoff.Sleeper;
|
||||
import org.springframework.retry.interceptor.RetryInterceptorBuilder;
|
||||
@@ -215,6 +217,18 @@ public class EnableRetryTests {
|
||||
@EnableRetry
|
||||
protected static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
public static PropertySourcesPlaceholderConfigurer pspc() {
|
||||
PropertySourcesPlaceholderConfigurer pspc = new PropertySourcesPlaceholderConfigurer();
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("one", "1");
|
||||
properties.setProperty("five", "5");
|
||||
properties.setProperty("onePointOne", "1.1");
|
||||
properties.setProperty("retryMethod", "shouldRetry");
|
||||
pspc.setProperties(properties);
|
||||
return pspc;
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@Bean
|
||||
public Sleeper sleeper() {
|
||||
@@ -447,9 +461,10 @@ public class EnableRetryTests {
|
||||
throw new RuntimeException("this cannot be retried");
|
||||
}
|
||||
|
||||
@Retryable(exceptionExpression="#{@exceptionChecker.shouldRetry(#root)}",
|
||||
@Retryable(exceptionExpression="#{@exceptionChecker.${retryMethod}(#root)}",
|
||||
maxAttemptsExpression = "#{@integerFiveBean}",
|
||||
backoff = @Backoff(delayExpression = "#{1}", maxDelayExpression = "#{5}", multiplierExpression = "#{1.1}"))
|
||||
backoff = @Backoff(delayExpression = "#{${one}}", maxDelayExpression = "#{${five}}",
|
||||
multiplierExpression = "#{${onePointOne}}"))
|
||||
public void service3() {
|
||||
if (count++ < 8) {
|
||||
throw new RuntimeException();
|
||||
|
||||
Reference in New Issue
Block a user