代码之家  ›  专栏  ›  技术社区  ›  cibercitizen1

Java方法缺失(ala Ruby)用于装饰?

  •  12
  • cibercitizen1  · 技术社区  · 14 年前

    在Java中是否有可用的技术来拦截消息(方法调用),比如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())

    4 回复  |  直到 14 年前
        1
  •  17
  •   killdash10    14 年前

    正如其他人已经正确地说过的,使用dynamicproxy。这里有一个例子。

    这个类使用dynamicProxy拦截在“hammerListener”接口中声明的方法调用。它做一些日志记录,然后委托给“真正的”hammerlistener实现(是的,同样的事情也可以用aop完成)。

    请参见代理实例化的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();
         }
    }
    
        2
  •  4
  •   skaffman    14 年前

    java.lang.reflect.Proxy 是为运行时指定的接口生成运行时代理的起点。它允许您指定要代理的接口,以及处理“真实”调用的对象,如果您选择,当然可以简单地调用其他对象。

    的输出 Proxy 类是一个对象,您可以将其转换为所需的接口类型,并像任何其他对象一样使用和调用它。

    它不会像露比这样的动态语言那么简单,但是你要为像Java这样的强静态语言付出代价。

        3
  •  2
  •   lexicore    14 年前

    请参见java.lang.reflect.proxy和java.lang.reflect.invocationhandler或面向方面编程(例如aspectj)。

        4
  •  0
  •   jsight TaherT    14 年前

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