All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.avaje.inject.aop.Invocation Maven / Gradle / Ivy

There is a newer version: 10.6-javax
Show newest version
package io.avaje.inject.aop;

import java.lang.reflect.Method;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * Method invocation used in {@link MethodInterceptor#invoke(Invocation)} for Aspects.
 * 

* Represents a method invocation that can be intercepted with additional before and after * invocation logic. */ public interface Invocation { /** * Invoke the underlying method returning the result. * * @return The result of the method call. This will return null for void methods. * @throws Throwable Exception thrown by underlying method */ Object invoke() throws Throwable; /** * Invoke the underlying method returning the result. Checked exceptions will be caught and * rethrown as {@code InvocationException}s. * * @return The result of the method call. This will return null for void methods. */ default Object invokeUnchecked() { try { return invoke(); } catch (final RuntimeException e) { throw e; } catch (final Throwable e) { throw new InvocationException(e); } } /** * Set the result that will be returned to the caller. *

* This will replace a prior result set by calling {@code #invoke} or can be used * to provide a result allowing to skip calling {@code #invoke} altogether. * * @param result The result that will be returned to the caller. */ void result(Object result); /** * Return the arguments used for this invocation. */ Object[] arguments(); /** * Return the method being called for this invocation. */ Method method(); /** * Return the 'this' instance of the invocation. *

* This is typically used when invoking fallback/recovery methods. */ Object instance(); /** * Return whether this invocation has a registered recovery method */ boolean hasRecoveryMethod(); /** * Invoke the recovery method associated for this invocation and return the result. * * @return The result of the method call. This will return null for void methods. * @throws IllegalStateException if no fallback method is configured with this invocation */ Object invokeRecoveryMethod(Throwable t); /** * Invocation base type for both callable and runnable methods. * * @param The result type */ abstract class Base implements Invocation { protected Method method; protected Object[] args; protected Object instance; protected T result; /** * Set the instance, method and arguments for the invocation. */ public Base with(Object instance, Method method, Object... args) { this.instance = instance; this.method = method; this.args = args; return this; } @SuppressWarnings("unchecked") @Override public void result(Object result) { this.result = (T) result; } /** * Return the final invocation result. */ public T finalResult() { return result; } @Override public Object[] arguments() { return args; } @Override public Method method() { return method; } @Override public Object instance() { return instance; } /** * Wrap this invocation using a methodInterceptor returning the wrapped call. *

* This invocation is effectively nested inside the returned invocation. * * @param methodInterceptor The method interceptor to use to wrap this call with * @return The wrapped call */ public abstract Base wrap(MethodInterceptor methodInterceptor); protected void noRecovery(Object recover) { if (recover == null) { throw new IllegalStateException("No recovery method available for this invocation"); } } } /** * Runnable based Invocation. */ final class Run extends Base { private final CheckedRunnable delegate; private Consumer fallback; /** * Create with a given closure to run. */ public Run(CheckedRunnable delegate) { this.delegate = delegate; } @Override public Object invoke() throws Throwable { delegate.invoke(); return null; } /** * Register a fallback method which can be used to recover from an exception * while intercepting an invocation */ public Run fallback(Consumer fallback) { this.fallback = fallback; return this; } @Override public Base wrap(MethodInterceptor methodInterceptor) { return new Invocation.Run(() -> methodInterceptor.invoke(this)).with(instance, method, args); } @Override public boolean hasRecoveryMethod() { return fallback != null; } @Override public Object invokeRecoveryMethod(Throwable t) { noRecovery(fallback); fallback.accept(t); return null; } @Override public Run with(Object instance, Method method, Object... args) { super.with(instance, method, args); return this; } } /** * Callable based Invocation with checked exceptions. */ final class Call extends Base { private final CheckedSupplier delegate; private Function fallback; /** * Create with a given supplier. */ public Call(CheckedSupplier delegate) { this.delegate = delegate; } @Override public Object invoke() throws Throwable { result = delegate.invoke(); return result; } @Override public T finalResult() { return result; } @Override public Call with(Object instance, Method method, Object... args) { super.with(instance, method, args); return this; } /** * register a fallback method which can be used to recover from an exception while intercepting * an invocation */ public Call fallback(Function fallback) { this.fallback = fallback; return this; } @Override public Base wrap(MethodInterceptor methodInterceptor) { return new Invocation.Call<>(() -> { final Call delegate = this; methodInterceptor.invoke(delegate); return delegate.finalResult(); }).with(instance, method, args); } @Override public boolean hasRecoveryMethod() { return fallback != null; } @Override public Object invokeRecoveryMethod(Throwable t) { noRecovery(fallback); var result = fallback.apply(t); super.result(result); return result; } } /** * Runnable with checked exceptions. */ @FunctionalInterface interface CheckedRunnable { /** * Invoke the method. */ void invoke() throws Throwable; } /** * Callable with checked exceptions. * * @param The result type */ @FunctionalInterface interface CheckedSupplier { /** * Invoke the method returning the result. */ T invoke() throws Throwable; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy