You can use Proxy
.
If you have an interface like this:
public interface ICL1 {
public String foo();
public String bar(String x);
}
and a class like this:
public class CL1 implements ICL1 {
@Override
public String foo() {
return "foo";
}
@Override
public String bar(String foo) {
return foo + "bar";
}
}
you can proxy it like this:
public class TProxy<T> implements InvocationHandler {
private final ExecutorService exe = Executors.newCachedThreadPool();
public final Object object;
private TProxy(T object) {
this.object = object;
}
public static <U> U getProxy(Class<U> intf, U target) {
return (U) Proxy.newProxyInstance(target.getClass().getClassLoader(), new Class[]{intf}, new TProxy(target));
}
@Override
public Object invoke(Object target, Method method, Object[] args) throws Throwable {
Future f = exe.submit(() -> method.invoke(object, args));
return f.get();
}
}
and then you can use the proxy like this:
System.out.println(TProxy.getProxy(ICL1.class, new CL1()).foo());
Spring does it all the time ;). Enjoy.
Note: this does not take care of the callback. My suggestion would be to annotate your methods with your own home cooked annotation containing some reference to a callback, possibly another Runnable
, or the name of a method in your interface. You can then use the annotation in the invoke
method of the Proxy. Make sure your annotation has retention Runtime
.