先来一个InvocationHandler示例,InvocationHandler类的作用是:对原始对象的方法做一个拦截。
package com.zhang; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; interface HelloSerivce { void sayHello(); void sayHi(); } interface FuckService { void fuck(); } class HelloServiceImpl implements HelloSerivce { @Override public void sayHello() { System.out.println("hello zhang"); } @Override public void sayHi() { System.out.println("hi zhang"); } } public class InvocationHandler_Test { public static void main(String[] args) { class MyInvocationHandler implements InvocationHandler { private Object obj; public MyInvocationHandler(Object obj) { this.obj = obj; } //拦截方法 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if ("sayHello".equals(method.getName())) { System.out.println("拦截sayHello"); } else if("sayHi".equals(method.getName())) { System.out.println("拦截sayHi"); } //调用原始方法 method.invoke(obj, args); return null; } @Override public String toString() { return "MyInvocationHandler:" + System.currentTimeMillis(); } } HelloSerivce helloSerivceImpl = new HelloServiceImpl(); MyInvocationHandler myInvocationHandler = new MyInvocationHandler(helloSerivceImpl); //生成代理 Class<?>[] src = HelloServiceImpl.class.getInterfaces(); Class<?>[] dest = new Class<?>[src.length + 1]; System.arraycopy(src, 0, dest, 0, src.length); dest[src.length] = FuckService.class; HelloSerivce proxyInstance = (HelloSerivce)Proxy.newProxyInstance(HelloServiceImpl.class.getClassLoader(), dest, myInvocationHandler); proxyInstance.sayHello(); proxyInstance.sayHi(); System.out.println(proxyInstance instanceof FuckService); FuckService fService = (FuckService)proxyInstance; //报错 fService.fuck(); } }
dubbo consumer的InvokerInvocationHandler实现了InvocationHandler接口,拦截的是MockClusterInvoker对象的方法,这是jdk动态代理。
public class InvokerInvocationHandler implements InvocationHandler { private final Invoker<?> invoker; public InvokerInvocationHandler(Invoker<?> handler){ this.invoker = handler; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); Class<?>[] parameterTypes = method.getParameterTypes(); //如果是Object的方法,直接调用原生对象的方法 if (method.getDeclaringClass() == Object.class) { return method.invoke(invoker, args); } //下面的判断其实是冗余的 if ("toString".equals(methodName) && parameterTypes.length == 0) { return invoker.toString(); } if ("hashCode".equals(methodName) && parameterTypes.length == 0) { return invoker.hashCode(); } if ("equals".equals(methodName) && parameterTypes.length == 1) { return invoker.equals(args[0]); } //剩下的就需要发送请求给provider了 return invoker.invoke(new RpcInvocation(method, args)).recreate(); } }
比较一下jdk和javassist动态代理:
//JdkProxyFactory @SuppressWarnings("unchecked") public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) { return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
interfaces, new InvokerInvocationHandler(invoker)); }
//JavassistProxyFactory @SuppressWarnings("unchecked") public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) { return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker)); }
存在HelloService接口:
public interface HelloService { String sayHello(); }
Javassist为它动态生成的类代码大致如下:
class com.alibaba.dubbo.common.bytecode.proxy0 implements com.alibaba.dubbo.rpc.service.EchoService, com.zhang.HelloService { public <init>(java.lang.reflect.InvocationHandler arg0){ handler=$1; } public static java.lang.reflect.Method[] methods; private java.lang.reflect.InvocationHandler handler; public java.lang.String sayHello(){ Object[] args = new Object[0]; //handler是InvokerInvocationHandler对象 Object ret = handler.invoke(this, methods[0], args); return (java.lang.String)ret; } public java.lang.Object $echo(java.lang.Object arg0){ Object[] args = new Object[1]; args[0] = ($w)$1; Object ret = handler.invoke(this, methods[1], args); return (java.lang.Object)ret; } }
从上面能看出来:Javassist动态生成的类直接调用InvocationHandler,不是通过代理调用的。