Java 后备模式
Java fallback pattern
我正在尝试找到一种很好的方式来实现依赖于第三方库的服务 class。我还有一个 'default' 实现,可在库不可用或无法提供答案时用作回退。
public interface Service {
public Object compute1();
public Object compute2();
}
public class DefaultService implements Service {
@Override
public Object compute1() {
// ...
}
@Override
public Object compute2() {
// ...
}
}
服务的实际实现类似于:
public class ServiceImpl implements Service {
Service defaultService = new DefaultService();
ThirdPartyService thirdPartyService = new ThirdPartyService();
@Override
public Object compute1() {
try {
Object obj = thirdPartyService.customCompute1();
return obj != null ? obj : defaultService.compute1();
}
catch (Exception e) {
return defaultService.compute1();
}
}
@Override
public Object compute2() {
try {
Object obj = thirdPartyService.customCompute2();
return obj != null ? obj : defaultService.compute2();
}
catch (Exception e) {
return defaultService.compute2();
}
}
}
当前的实现似乎有点重复,只是对服务的实际调用不同,但 try/catch 和默认机制几乎相同。此外,如果在服务中添加另一种方法,实现看起来几乎是一样的。
最好的库之一是 Netflix 的 Hystrix。我不确定你是否需要这么繁重的工作。它会给你线程池、超时、回退、监控、运行时配置更改、短路等
基本上它是一个库,可以保护您的代码免受其依赖项故障的影响。
代理可能会在这里帮助您。下面的示例未经测试,但应该让您了解可以放置什么:
public class FallbackService implements InvocationHandler {
private final Service primaryService;
private final Service fallbackService;
private FallbackService(Service primaryService, Service fallbackService) {
this.primaryService = primaryService;
this.fallbackService = fallbackService;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
Object result = method.invoke(primaryService, args);
if (result != null) return result;
} catch (Exception ignore) {}
return method.invoke(fallbackService, args);
}
public static Service createFallbackService(Service primaryService, Service fallbackService) {
return (Service) Proxy.newProxyInstance(
Service.class.getClassLoader(),
new Class[] { Service.class },
new FallbackService(primaryService, fallbackService)
);
}
}
您可以使用方法引用将通用逻辑提取到单独的方法中,例如:
public class ServiceImpl implements Service {
Service defaultService = new DefaultService();
ThirdPartyService thirdPartyService = new ThirdPartyService();
@Override
public Object compute1() {
return run(thirdPartyService::customCompute1, defaultService::compute1);
}
@Override
public Object compute2() {
return run(thirdPartyService::customCompute2, defaultService::compute2);
}
private static <T> T run(Supplier<T> action, Supplier<T> fallback) {
try {
T result = action.get();
return result != null ? result : fallback.get();
} catch(Exception e) {
return fallback.get();
}
}
}
我正在尝试找到一种很好的方式来实现依赖于第三方库的服务 class。我还有一个 'default' 实现,可在库不可用或无法提供答案时用作回退。
public interface Service {
public Object compute1();
public Object compute2();
}
public class DefaultService implements Service {
@Override
public Object compute1() {
// ...
}
@Override
public Object compute2() {
// ...
}
}
服务的实际实现类似于:
public class ServiceImpl implements Service {
Service defaultService = new DefaultService();
ThirdPartyService thirdPartyService = new ThirdPartyService();
@Override
public Object compute1() {
try {
Object obj = thirdPartyService.customCompute1();
return obj != null ? obj : defaultService.compute1();
}
catch (Exception e) {
return defaultService.compute1();
}
}
@Override
public Object compute2() {
try {
Object obj = thirdPartyService.customCompute2();
return obj != null ? obj : defaultService.compute2();
}
catch (Exception e) {
return defaultService.compute2();
}
}
}
当前的实现似乎有点重复,只是对服务的实际调用不同,但 try/catch 和默认机制几乎相同。此外,如果在服务中添加另一种方法,实现看起来几乎是一样的。
最好的库之一是 Netflix 的 Hystrix。我不确定你是否需要这么繁重的工作。它会给你线程池、超时、回退、监控、运行时配置更改、短路等
基本上它是一个库,可以保护您的代码免受其依赖项故障的影响。
代理可能会在这里帮助您。下面的示例未经测试,但应该让您了解可以放置什么:
public class FallbackService implements InvocationHandler {
private final Service primaryService;
private final Service fallbackService;
private FallbackService(Service primaryService, Service fallbackService) {
this.primaryService = primaryService;
this.fallbackService = fallbackService;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
Object result = method.invoke(primaryService, args);
if (result != null) return result;
} catch (Exception ignore) {}
return method.invoke(fallbackService, args);
}
public static Service createFallbackService(Service primaryService, Service fallbackService) {
return (Service) Proxy.newProxyInstance(
Service.class.getClassLoader(),
new Class[] { Service.class },
new FallbackService(primaryService, fallbackService)
);
}
}
您可以使用方法引用将通用逻辑提取到单独的方法中,例如:
public class ServiceImpl implements Service {
Service defaultService = new DefaultService();
ThirdPartyService thirdPartyService = new ThirdPartyService();
@Override
public Object compute1() {
return run(thirdPartyService::customCompute1, defaultService::compute1);
}
@Override
public Object compute2() {
return run(thirdPartyService::customCompute2, defaultService::compute2);
}
private static <T> T run(Supplier<T> action, Supplier<T> fallback) {
try {
T result = action.get();
return result != null ? result : fallback.get();
} catch(Exception e) {
return fallback.get();
}
}
}