本文主要研究一下spring cloud的consulRetryInterceptor
spring-cloud-consul-core-2.1.2.RELEASE-sources.jar!/org/springframework/cloud/consul/ConsulAutoConfiguration.java
@Configuration @EnableConfigurationProperties @ConditionalOnConsulEnabled public class ConsulAutoConfiguration { //...... @ConditionalOnClass({ Retryable.class, Aspect.class, AopAutoConfiguration.class }) @Configuration @EnableRetry(proxyTargetClass = true) @Import(AopAutoConfiguration.class) @EnableConfigurationProperties(RetryProperties.class) protected static class RetryConfiguration { @Bean(name = "consulRetryInterceptor") @ConditionalOnMissingBean(name = "consulRetryInterceptor") public RetryOperationsInterceptor consulRetryInterceptor( RetryProperties properties) { return RetryInterceptorBuilder.stateless() .backOffOptions(properties.getInitialInterval(), properties.getMultiplier(), properties.getMaxInterval()) .maxAttempts(properties.getMaxAttempts()).build(); } } //...... }
spring-cloud-consul-core-2.1.2.RELEASE-sources.jar!/org/springframework/cloud/consul/RetryProperties.java
@ConfigurationProperties("spring.cloud.consul.retry") public class RetryProperties { /** Initial retry interval in milliseconds. */ private long initialInterval = 1000; /** Multiplier for next interval. */ private double multiplier = 1.1; /** Maximum interval for backoff. */ private long maxInterval = 2000; /** Maximum number of attempts. */ private int maxAttempts = 6; public RetryProperties() { } public long getInitialInterval() { return this.initialInterval; } public void setInitialInterval(long initialInterval) { this.initialInterval = initialInterval; } public double getMultiplier() { return this.multiplier; } public void setMultiplier(double multiplier) { this.multiplier = multiplier; } public long getMaxInterval() { return this.maxInterval; } public void setMaxInterval(long maxInterval) { this.maxInterval = maxInterval; } public int getMaxAttempts() { return this.maxAttempts; } public void setMaxAttempts(int maxAttempts) { this.maxAttempts = maxAttempts; } @Override public String toString() { return new ToStringCreator(this).append("initialInterval", this.initialInterval) .append("multiplier", this.multiplier) .append("maxInterval", this.maxInterval) .append("maxAttempts", this.maxAttempts).toString(); } }
spring-boot-autoconfigure-2.1.6.RELEASE-sources.jar!/org/springframework/boot/autoconfigure/aop/AopAutoConfiguration.java
@Configuration @ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class, AnnotatedElement.class }) @ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true) public class AopAutoConfiguration { @Configuration @EnableAspectJAutoProxy(proxyTargetClass = false) @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false) public static class JdkDynamicAutoProxyConfiguration { } @Configuration @EnableAspectJAutoProxy(proxyTargetClass = true) @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true) public static class CglibAutoProxyConfiguration { } }
spring.aop.proxy-target-class
来注入不同的代理方式,默认是cglib代理 spring-retry-1.2.4.RELEASE-sources.jar!/org/springframework/retry/interceptor/RetryOperationsInterceptor.java
public class RetryOperationsInterceptor implements MethodInterceptor { private RetryOperations retryOperations = new RetryTemplate(); private MethodInvocationRecoverer<?> recoverer; private String label; public void setLabel(String label) { this.label = label; } public void setRetryOperations(RetryOperations retryTemplate) { Assert.notNull(retryTemplate, "'retryOperations' cannot be null."); this.retryOperations = retryTemplate; } public void setRecoverer(MethodInvocationRecoverer<?> recoverer) { this.recoverer = recoverer; } public Object invoke(final MethodInvocation invocation) throws Throwable { String name; if (StringUtils.hasText(label)) { name = label; } else { name = invocation.getMethod().toGenericString(); } final String label = name; RetryCallback<Object, Throwable> retryCallback = new RetryCallback<Object, Throwable>() { public Object doWithRetry(RetryContext context) throws Exception { context.setAttribute(RetryContext.NAME, label); /* * If we don't copy the invocation carefully it won't keep a reference to * the other interceptors in the chain. We don't have a choice here but to * specialise to ReflectiveMethodInvocation (but how often would another * implementation come along?). */ if (invocation instanceof ProxyMethodInvocation) { try { return ((ProxyMethodInvocation) invocation).invocableClone().proceed(); } catch (Exception e) { throw e; } catch (Error e) { throw e; } catch (Throwable e) { throw new IllegalStateException(e); } } else { throw new IllegalStateException( "MethodInvocation of the wrong type detected - this should not happen with Spring AOP, " + "so please raise an issue if you see this exception"); } } }; if (recoverer != null) { ItemRecovererCallback recoveryCallback = new ItemRecovererCallback( invocation.getArguments(), recoverer); return this.retryOperations.execute(retryCallback, recoveryCallback); } return this.retryOperations.execute(retryCallback); } /** * @author Dave Syer * */ private static final class ItemRecovererCallback implements RecoveryCallback<Object> { private final Object[] args; private final MethodInvocationRecoverer<?> recoverer; /** * @param args the item that failed. */ private ItemRecovererCallback(Object[] args, MethodInvocationRecoverer<?> recoverer) { this.args = Arrays.asList(args).toArray(); this.recoverer = recoverer; } public Object recover(RetryContext context) { return recoverer.recover(args, context.getLastThrowable()); } } }