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

cib*_*en1 12 java decorator

Java中是否有任何可用于拦截消息(方法调用)的技术,如Ruby中的method_missing技术?这将允许非常容易地编码装饰器和代理,就像在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
Run Code Online (Sandbox Code Playgroud)

(注意:代理只有一个方法:method_missing())

kil*_*h10 17

正如其他人已经正确说过的那样,使用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();
     }
}
Run Code Online (Sandbox Code Playgroud)