序
本文主要研究一下resilience4j的fallback
使用实例
@Test
public void testFallback(){
// Execute the decorated supplier and recover from any exception
String result = Try.ofSupplier(() -> backendService.doSomethingThrowException())
.recover(throwable -> "Hello from Recovery").get();
System.out.println(result);
}
Try
vavr-0.9.2-sources.jar!/io/vavr/control/Try.java
/**
* The Try control gives us the ability write safe code without focusing on try-catch blocks in the presence of exceptions.
*
* The following exceptions are considered to be fatal/non-recoverable:
*
* - {@linkplain InterruptedException}
* - {@linkplain LinkageError}
* - {@linkplain ThreadDeath}
* - {@linkplain VirtualMachineError} (i.e. {@linkplain OutOfMemoryError} or {@linkplain StackOverflowError})
*
*
* Important note: Try may re-throw (undeclared) exceptions, e.g. on {@code get()}. From within a
* dynamic proxy {@link java.lang.reflect.InvocationHandler} this will lead to an
* {@link java.lang.reflect.UndeclaredThrowableException}. For more information, please read
* Dynamic Proxy Classes.
*
* @param Value type in the case of success.
* @author Daniel Dietrich
*/
public interface Try extends Value, Serializable {
long serialVersionUID = 1L;
/**
* Creates a Try of a CheckedFunction0.
*
* @param supplier A checked supplier
* @param Component type
* @return {@code Success(supplier.apply())} if no exception occurs, otherwise {@code Failure(throwable)} if an
* exception occurs calling {@code supplier.apply()}.
*/
static Try of(CheckedFunction0 extends T> supplier) {
Objects.requireNonNull(supplier, "supplier is null");
try {
return new Success<>(supplier.apply());
} catch (Throwable t) {
return new Failure<>(t);
}
}
/**
* Creates a Try of a Supplier.
*
* @param supplier A supplier
* @param Component type
* @return {@code Success(supplier.get())} if no exception occurs, otherwise {@code Failure(throwable)} if an
* exception occurs calling {@code supplier.get()}.
*/
static Try ofSupplier(Supplier extends T> supplier) {
Objects.requireNonNull(supplier, "supplier is null");
return of(supplier::get);
}
/**
* Creates a Try of a Callable.
*
* @param callable A callable
* @param Component type
* @return {@code Success(callable.call())} if no exception occurs, otherwise {@code Failure(throwable)} if an
* exception occurs calling {@code callable.call()}.
*/
static Try ofCallable(Callable extends T> callable) {
Objects.requireNonNull(callable, "callable is null");
return of(callable::call);
}
//......
}
- 这个Try继承了Value接口
- 另外就是提供了一些静态工厂方法,ofSupplier方法会触发方法的执行,如果成功返回Success,有异常返回Failure
Try.Success
vavr-0.9.2-sources.jar!/io/vavr/control/Try.java
/**
* A succeeded Try.
*
* @param component type of this Success
* @author Daniel Dietrich
*/
final class Success implements Try, Serializable {
private static final long serialVersionUID = 1L;
private final T value;
/**
* Constructs a Success.
*
* @param value The value of this Success.
*/
private Success(T value) {
this.value = value;
}
@Override
public T get() {
return value;
}
@Override
public Throwable getCause() {
throw new UnsupportedOperationException("getCause on Success");
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public boolean isFailure() {
return false;
}
@Override
public boolean isSuccess() {
return true;
}
@Override
public boolean equals(Object obj) {
return (obj == this) || (obj instanceof Success && Objects.equals(value, ((Success>) obj).value));
}
@Override
public int hashCode() {
return Objects.hashCode(value);
}
@Override
public String stringPrefix() {
return "Success";
}
@Override
public String toString() {
return stringPrefix() + "(" + value + ")";
}
}
- isFailure方法返回false
Try.Failure
vavr-0.9.2-sources.jar!/io/vavr/control/Try.java
/**
* A failed Try.
*
* @param component type of this Failure
* @author Daniel Dietrich
*/
final class Failure implements Try, Serializable {
private static final long serialVersionUID = 1L;
private final Throwable cause;
/**
* Constructs a Failure.
*
* @param cause A cause of type Throwable, may not be null.
* @throws NullPointerException if {@code cause} is null
* @throws Throwable if the given {@code cause} is fatal, i.e. non-recoverable
*/
private Failure(Throwable cause) {
Objects.requireNonNull(cause, "cause is null");
if (isFatal(cause)) {
sneakyThrow(cause);
}
this.cause = cause;
}
@Override
public T get() {
return sneakyThrow(cause);
}
@Override
public Throwable getCause() {
return cause;
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public boolean isFailure() {
return true;
}
@Override
public boolean isSuccess() {
return false;
}
@Override
public boolean equals(Object obj) {
return (obj == this) || (obj instanceof Failure && Arrays.deepEquals(cause.getStackTrace(), ((Failure>) obj).cause.getStackTrace()));
}
@Override
public String stringPrefix() {
return "Failure";
}
@Override
public int hashCode() {
return Arrays.hashCode(cause.getStackTrace());
}
@Override
public String toString() {
return stringPrefix() + "(" + cause + ")";
}
}
- isFailure方法返回true
recover
vavr-0.9.2-sources.jar!/io/vavr/control/Try.java
/**
* Returns {@code this}, if this is a {@code Success}, otherwise tries to recover the exception of the failure with {@code f},
* i.e. calling {@code Try.of(() -> f.apply(throwable))}.
*
* @param f A recovery function taking a Throwable
* @return a {@code Try}
* @throws NullPointerException if {@code f} is null
*/
default Try recover(Function super Throwable, ? extends T> f) {
Objects.requireNonNull(f, "f is null");
if (isFailure()) {
return Try.of(() -> f.apply(getCause()));
} else {
return this;
}
}
- 这个recover方法,首先通过isFailure方法判断是否失败
- 如果失败的话,则调用fallback方法。
小结
- resilience4j的Try有两个实现,一个是Success,一个Failure,他们都实现isFailure方法。
- Try接口有个默认的方法recover,用来实现fallback,它首先判断是不是方法调用失败,如果是才执行fallback方法。
- 整个fallback的实现就是类似try catch然后调用fallback方法
doc
- Resilience4j is a fault tolerance library designed for Java8 and functional programming