装饰缺少Java方法(ala Ruby)?

装饰缺少Java方法(ala Ruby)?,java,decorator,Java,Decorator,Java中是否有任何技术可以用来拦截消息(方法调用),比如Ruby中的method_missing技术?这将允许对decorator和代理进行编码 很容易,就像在Ruby中: :Client p:Proxy im:Implementation ------- ---------- ----------------- p.foo() -------> method_missin

Java中是否有任何技术可以用来拦截消息(方法调用),比如Ruby中的method_missing技术?这将允许对decorator和代理进行编码 很容易,就像在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())

不完全正确。最接近的等价物是对象,但它有一些限制(即只能通过反射调用)。

请参见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();
     }
}

你怎么会有这个想法?代理对象可以像任何其他对象一样进行强制转换和调用。“代理实现的接口上的所有方法调用”--因此,如果您想拦截任何可能的方法调用,那么就没有用了?我认为原始海报希望能够捕获对不存在的方法的调用。如果可能的话,那将是令人惊讶的。