[case28]聊聊resilience4j的fallback

本文主要研究一下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 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 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 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 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

你可能感兴趣的:(resilience4j)