装饰缺少Java方法(ala Ruby)?
Java中是否有任何技术可以用来拦截消息(方法调用),比如Ruby中的method_missing技术?这将允许对decorator和代理进行编码 很容易,就像在Ruby中:装饰缺少Java方法(ala Ruby)?,java,decorator,Java,Decorator,Java中是否有任何技术可以用来拦截消息(方法调用),比如Ruby中的method_missing技术?这将允许对decorator和代理进行编码 很容易,就像在Ruby中: :Client p:Proxy im:Implementation ------- ---------- ----------------- p.foo() -------> method_missin
: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())不完全正确。最接近的等价物是对象,但它有一些限制(即只能通过反射调用)。请参见java.lang.reflect.Proxy和java.lang.reflect.InvocationHandler或一般的面向方面编程(例如AspectJ).是为运行时指定的接口生成运行时代理的起点。它允许您指定要代理的接口,以及处理“真实”调用的对象,如果您选择,当然可以简单地调用其他对象
Proxy
类的输出是一个对象,您可以将其转换为所需的接口类型,并像任何其他对象一样使用和调用
这不会像使用Ruby这样的动态语言那么容易,但是您要为Java这样的强静态语言付出代价。正如其他人已经正确说过的,使用DynamicProxy。这里有一个例子 此类使用DynamicProxy拦截对“HammerListener”接口中声明的方法的调用。它做一些日志记录,然后委托给“真正的”HammerListener实现(是的,AOP也可以做同样的事情) 请参阅代理实例化的newInstance方法(注意,您需要传入代理应该实现的接口-代理可以实现多个接口)
代理实现的接口上的所有方法调用最终都将作为对“invoke”方法的调用,该方法在“invokinghandler”接口中声明。所有代理处理程序都必须实现此接口
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();
}
}
你怎么会有这个想法?代理对象可以像任何其他对象一样进行强制转换和调用。“代理实现的接口上的所有方法调用”--因此,如果您想拦截任何可能的方法调用,那么就没有用了?我认为原始海报希望能够捕获对不存在的方法的调用。如果可能的话,那将是令人惊讶的。