Действительно ли там какая-либо техника доступна в Java для прерывания сообщений (вызовы метода) как method_missing техника в Ruby? Это позволило бы кодировать декораторов и прокси очень легко, как в Ruby:
:Client p:Proxy im:Implementation
------- ---------- -----------------
p.foo() -------> method_missing()
do_something
im.foo() ------------------> do_foo
p.bar() --------> method_missing()
do_something_more
im.bar() -------------------> do_bar
(Примечание: Прокси только имеет один метод: method_missing ())
Как уже правильно сказали другие, используйте DynamicProxy. Вот пример.
Этот класс использует DynamicProxy для перехвата вызовов методов, объявленных в интерфейсе «HammerListener». Он выполняет некоторое протоколирование, а затем делегирует «настоящую» реализацию HammerListener (да, то же самое можно сделать и с АОП).
См. Метод newInstance для создания экземпляра прокси (обратите внимание, что вам необходимо передать интерфейс (ы), которые должен реализовать прокси - прокси может реализовывать несколько интерфейсов).
Все вызовы методов на интерфейсах, которые реализует прокси, будут завершаться вызовами метода «invoke», который объявлен в интерфейсе «InvocationHandler». Все обработчики прокси должны реализовать этот интерфейс.
import java.lang.reflect.*;
/**
* Decorates a HammerListener instance, adding BEFORE/AFTER
* log messages around all methods exposed in the HammerListener interface.
*/
public class HammerListenerDecorator implements InvocationHandler {
private final HammerListener delegate;
static HammerListener newInstance(HammerListener delegate) {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
return (HammerListener)Proxy.newProxyInstance(cl, new Class[]{HammerListener.class},
new HammerListenerDecorator(delegate));
}
private HammerListenerDecorator(HammerListener delegate) {
this.delegate = delegate;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
logger.info("BEFORE " + method.getName() + " {{{" + argsToString(args) + "}}}");
Object rtn = method.invoke(delegate, args);
logger.info("AFTER " + method.getName());
return rtn;
}
private String argsToString(Object[] args) {
StringBuilder sb = new StringBuilder();
for (Object o : args) {
sb.append(String.valueOf(o)).append(" ");
}
return sb.toString();
}
}
java.lang.reflect.Proxy
- это отправная точка для создания прокси во время выполнения для интерфейсов, которые вы указываете во время выполнения. Он позволяет вам указать интерфейс, который будет проксироваться, а также объект, который обрабатывает "реальный" вызов, который, по вашему желанию, может просто вызвать что-то другое.
Выход класса Proxy
- это объект, который вы можете привести к желаемому типу интерфейса, использовать и вызывать как любой другой объект.
Это будет не так просто, как с динамическим языком вроде Ruby, но вы платите цену за сильно статический язык вроде Java.
См. Java.lang.reflect.Proxy и java.lang.reflect.InvocationHandler или аспектно-ориентированное программирование в целом (например, AspectJ).
Не совсем так. Ближайшим эквивалентом является объект Dynamic Proxy , но он имеет некоторые ограничения (т. Е. Его можно вызывать только через отражение).