Spring 重试:如何使@Bean 的所有方法都可重试?
Spring Retry: How to make all methods of a @Bean retryable?
我想创建一个 @Bean
第三方服务,如 Keycloak(或任何其他服务),在任何给定时间可能无法访问。该对象应该重试生成的 Keycloak
bean 的所有方法。
我尝试了以下方法:
@Configuration
@EnableRetry
class KeycloakBeanProvider() {
@Bean
@Retryable
fun keycloak(oauth2ClientRegistration: ClientRegistration): Keycloak {
return KeycloakBuilder.builder()
.serverUrl(serverUrl)
.realm(oauth2ClientRegistration.clientName)
.grantType(OAuth2Constants.CLIENT_CREDENTIALS)
.clientId(oauth2ClientRegistration.clientId)
.clientSecret(oauth2ClientRegistration.clientSecret)
.build()
}
}
但是这样只会重试 bean 创建,而不是对 bean 的实际方法调用。我知道 @Retryable
可以在 class 级别上使用,但我没有 Keycloak
class 级别,所以我无法在此处添加它。
如何使生成的 Keycloak
bean 的方法可重试?
您必须将 Keycloak
注释为 @Retryable
。
@SpringBootApplication
@EnableRetry
public class So70593939Application {
public static void main(String[] args) {
SpringApplication.run(So70593939Application.class, args);
}
@Bean
ApplicationRunner runner(Foo foo) {
return args -> {
foo.foo("called foo");
foo.bar("called bar");
};
}
}
@Component
@Retryable
class Foo {
public void foo(String in) {
System.out.println("foo");
throw new RuntimeException("test");
}
public void bar(String in) {
System.out.println("bar");
throw new RuntimeException("test");
}
@Recover
public void recover(Exception ex, String in) {
System.out.println(ex.getMessage() + ":" + in);
}
}
foo
foo
foo
test:called foo
bar
bar
bar
test:called bar
如果您无法注释 class(例如,因为它来自另一个项目),您需要使用 RetryTemplate
来调用其方法,而不是使用基于注释的重试。
您可以手动检测您的 class。检查 documentation.
@Bean
public Keycloak myService() {
ProxyFactory factory = new ProxyFactory(RepeatOperations.class.getClassLoader());
factory.setInterfaces(Keycloak.class);
factory.setTarget(createKeycloak());
Keycloak keycloak = (Keycloak) factory.getProxy();
JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut();
pointcut.setPatterns(".*.*");
RetryOperationsInterceptor interceptor = new RetryOperationsInterceptor();
((Advised) keycloak).addAdvisor(new DefaultPointcutAdvisor(pointcut, interceptor));
return keycloak;
}
我想创建一个 @Bean
第三方服务,如 Keycloak(或任何其他服务),在任何给定时间可能无法访问。该对象应该重试生成的 Keycloak
bean 的所有方法。
我尝试了以下方法:
@Configuration
@EnableRetry
class KeycloakBeanProvider() {
@Bean
@Retryable
fun keycloak(oauth2ClientRegistration: ClientRegistration): Keycloak {
return KeycloakBuilder.builder()
.serverUrl(serverUrl)
.realm(oauth2ClientRegistration.clientName)
.grantType(OAuth2Constants.CLIENT_CREDENTIALS)
.clientId(oauth2ClientRegistration.clientId)
.clientSecret(oauth2ClientRegistration.clientSecret)
.build()
}
}
但是这样只会重试 bean 创建,而不是对 bean 的实际方法调用。我知道 @Retryable
可以在 class 级别上使用,但我没有 Keycloak
class 级别,所以我无法在此处添加它。
如何使生成的 Keycloak
bean 的方法可重试?
您必须将 Keycloak
注释为 @Retryable
。
@SpringBootApplication
@EnableRetry
public class So70593939Application {
public static void main(String[] args) {
SpringApplication.run(So70593939Application.class, args);
}
@Bean
ApplicationRunner runner(Foo foo) {
return args -> {
foo.foo("called foo");
foo.bar("called bar");
};
}
}
@Component
@Retryable
class Foo {
public void foo(String in) {
System.out.println("foo");
throw new RuntimeException("test");
}
public void bar(String in) {
System.out.println("bar");
throw new RuntimeException("test");
}
@Recover
public void recover(Exception ex, String in) {
System.out.println(ex.getMessage() + ":" + in);
}
}
foo
foo
foo
test:called foo
bar
bar
bar
test:called bar
如果您无法注释 class(例如,因为它来自另一个项目),您需要使用 RetryTemplate
来调用其方法,而不是使用基于注释的重试。
您可以手动检测您的 class。检查 documentation.
@Bean
public Keycloak myService() {
ProxyFactory factory = new ProxyFactory(RepeatOperations.class.getClassLoader());
factory.setInterfaces(Keycloak.class);
factory.setTarget(createKeycloak());
Keycloak keycloak = (Keycloak) factory.getProxy();
JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut();
pointcut.setPatterns(".*.*");
RetryOperationsInterceptor interceptor = new RetryOperationsInterceptor();
((Advised) keycloak).addAdvisor(new DefaultPointcutAdvisor(pointcut, interceptor));
return keycloak;
}