动态代理回顾
- 几乎所有java相关框架都需要采用动态代理工具; 【个人理解有以下两点】
- 强类型:java是强类型语言,在编译阶段有类型检测
- 切面编程:在用户代码执行之前、之后... 织入通用处理逻辑
- jdk动态代理相关类有java.lang.reflect.Proxy,java.lang.reflect.InvocationHandler
- jdk创建代理类需要实现InvocationHandler接口,并作为参数进一步可创建对应代理Proxy类
- InvocationHandler :Object invoke(Object proxy, Method method, Object[] args) 只有一个接口方法, 通常我们只需实现该方法,不会显式调用,proxy对象会调用该方法
- proxy:被代理对象 可进行嵌套如 proxy1 -> proxy2 -> ... -> originObject
- 当调用proxy对象方法时,会调用到InvocationHandler#invoke 方法
- jdk动态代理需要有接口定义;Javassist或asm 组件可以没有接口
- 动态代理相关文档链接
概述
- dubbo提供的动态代理工厂有JdkProxyFactory,JavassistProxyFactory
- 通过ProxyFactory接口的@SPI注解可看到默认实现是JavassistProxyFactory
- 使用Javassist生成代理类文件的核心类有 Proxy, Wrapper
dubbo 动态代理层的作用与必要性
-
图中的rpc调用没画出序列化、网络层... 【本文忽略】
-
proxy-client,proxy-server仅表示RPC框架中代理层;具体创建的代理对象会有很多个
-
客户端与服务端通常部署在不同服务器上,那么接口调用与实现需要发送网络请求
-
client端调用rpc方法时:
- 可显式调用rpc接口每个方法,实际是调用代理类的方法【必须有rpc接口实现类代理】
- method通常拆解为 类、方法名、参数、返回值类型...等数据
- 任何接口方法在proxy中无非是className,methodName,paramType, paramValue... 等数据;
- 由具体接口方法 ---> 代理对象方法 ---> 封装方法数据为req ---> send req
-
server端接收到rpc方法请求时:
- 解析req方法数据,并创建对应代理对象;
- 为什么不创建具体的rpc接口实现类对象?框架代码内部没法调用具体实现类的方法,只能调用代理类Proxy的方法;
- Proxy在用户代码运行时采用反射引用到具体的实现类
- receive req ---> 解析req数据 ---> 代理对象 ---> 接口实现类
dubbo动态代理
-
ProxyFactory默认采用JavassistProxyFactory实现
@SPI("javassist") public interface ProxyFactory { // 阅读代码过程中 发现该方法在服务引用阶段调用多一些【有例外】 // 若在服务引用阶段调用,通常需要根据引用rpc接口创建对应的invoker实例 // 创建非范化调用代理对象 @Adaptive({PROXY_KEY}) <T> T getProxy(Invoker<T> invoker) throws RpcException; // 阅读代码过程中 发现该方法在服务引用阶段调用多一些【有例外】 // 若在服务引用阶段调用,通常需要根据引用rpc接口创建对应的invoker实例 // generic: 控制是否范化代理对象 @Adaptive({PROXY_KEY}) <T> T getProxy(Invoker<T> invoker, boolean generic) throws RpcException; // 阅读代码过程中 发现该方法在服务暴露阶段调用多一些【有例外】 // proxy:rpc接口实现类,或其他... @Adaptive({PROXY_KEY}) <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException; } -
JavassistProxyFactory 有出现两个核心类Proxy,Wrapper
-
注意Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker)); 返回值不是Proxy类型
public class JavassistProxyFactory extends AbstractProxyFactory { @Override public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) { // Proxy#getProxy 返回 Proxy对象 // 在调用newInstance方法传入 invoker【被代理对象】 // 【重点】生成具体代理对象【具体代理类的 ClassType 不是 org.apache.dubbo.common.bytecode.Proxy】 return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker)); } @Override public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) { // 创建Wrapper包装类【请注意:不需要用到具体的 proxy引用,只需className即可】 final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type); // 创建Invoker对象,此处需要传入被代理对象proxy【如:rpc接口实现类】 return new AbstractProxyInvoker<T>(proxy, type, url) { // 该方法类似与 InvocationHandler :Object invoke(Object proxy, Method method, Object[] args) @Override protected Object doInvoke(T proxy, String methodName, Class<?>[] parameterTypes, Object[] arguments) throws Throwable { // AbstractProxyInvoker#invoke方法会调用doInvoke方法 // doInvoke方法会调用wrapper#invokeMethod // wrapper#invokeMethod方法会调用proxy对应的方法 return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments); } }; } }
dubbo Wrapper代理类创建分析
-
testDemoProtocol方法中执行protocol.export(invoker) 方法时需要传入invoker
-
该invoker通过proxyFactory.getInvoker(***)进行创建【通常proxyFactory.getInvoker 在服务暴露阶段会被调用到;也有例外】
-
默认调用JavassistProxyFactory#getInvoker方法;进一步调用Wrapper相关方法
public class DubboProtocolTest { private Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); private ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); @Test public void testDemoProtocol() throws Exception { // 接口实现对象【被代理对象】 DemoService service = new DemoServiceImpl(); int port = NetUtils.getAvailablePort(); // 分析入口:服务暴露阶段调用 Proxy#getInvoker【有例外】 protocol.export(proxyFactory.getInvoker(service, DemoService.class, URL.valueOf("dubbo://127.0.0.1:" + port + "/" + DemoService.class.getName() + "?codec=exchange"))); service = proxyFactory.getProxy(protocol.refer(DemoService.class, URL.valueOf("dubbo://127.0.0.1:" + port + "/" + DemoService.class.getName() + "?codec=exchange").addParameter("timeout", 3000L))); assertEquals(service.getSize(new String[]{"", "", ""}), 3); } 。。。 }
org.apache.dubbo.common.bytecode.Wrapper
-
proxy.getInvoker(***) 会执行Wrapper#getWrapper方法
-
Wrapper#makeWrapper 主要调用javassist api 生成动态代理类
-
debug到 cc.toClass() 时手动运行cc.mCtc.writeFile("/doc"); 则会在/doc/** 相关目录看到Wrapper*.class 文件
public abstract class Wrapper { private static final Map<Class<?>, Wrapper> WRAPPER_MAP = new ConcurrentHashMap<Class<?>, Wrapper>(); //class wrapper map private static final String[] EMPTY_STRING_ARRAY = new String[0]; private static final String[] OBJECT_METHODS = new String[]{"getClass", "hashCode", "toString", "equals"}; private static AtomicLong WRAPPER_CLASS_COUNTER = new AtomicLong(0); // 此处的参数对象Class 通常是被代理【如:rpc接口实现类】对象的class public static Wrapper getWrapper(Class<?> c) { // 已经是动态代理类型则返回 while (ClassGenerator.isDynamicClass(c)) // can not wrapper on dynamic class. { c = c.getSuperclass(); } if (c == Object.class) { return OBJECT_WRAPPER; } // 会有缓存 return WRAPPER_MAP.computeIfAbsent(c, key -> makeWrapper(key)); } // 创建动态代理Wrapper类 // 调用Javassist工具类生成class文件,该方法很长 【已删除很多代码】 // 对Javassist api感兴趣的读者可阅读源码 private static Wrapper makeWrapper(Class<?> c) { if (c.isPrimitive()) { throw new IllegalArgumentException("Can not create wrapper for primitive type: " + c); } String name = c.getName(); ClassLoader cl = ClassUtils.getClassLoader(c); StringBuilder c1 = new StringBuilder("public void setPropertyValue(Object o, String n, Object v){ "); StringBuilder c2 = new StringBuilder("public Object getPropertyValue(Object o, String n){ "); StringBuilder c3 = new StringBuilder("public Object invokeMethod(Object o, String n, Class[] p, Object[] v) throws " + InvocationTargetException.class.getName() + "{ "); c1.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }"); c2.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }"); c3.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }"); Map<String, Class<?>> pts = new HashMap<>(); // <property name, property types> Map<String, Method> ms = new LinkedHashMap<>(); // <method desc, Method instance> List<String> mns = new ArrayList<>(); // method names. List<String> dmns = new ArrayList<>(); // declaring method names. for (Map.Entry<String, Method> entry : ms.entrySet()) { 。。。 } long id = WRAPPER_CLASS_COUNTER.getAndIncrement(); ClassGenerator cc = ClassGenerator.newInstance(cl); // 动态代理类名通常为Wrapper0,Wrapper1 ... // 动态代理类 与Wrapper在同一个包下 cc.setClassName((Modifier.isPublic(c.getModifiers()) ? Wrapper.class.getName() : c.getName() + "$sw") + id); // 动态代理类extends Wrapper cc.setSuperClass(Wrapper.class); try { // 生成Class类 // debug到此处手动运行 cc.mCtc.writeFile("/doc"); 可生成动态代理类class文件 反编译可看到对应代码 Class<?> wc = cc.toClass(); // setup static field. wc.getField("pts").set(null, pts); wc.getField("pns").set(null, pts.keySet().toArray(new String[0])); wc.getField("mns").set(null, mns.toArray(new String[0])); wc.getField("dmns").set(null, dmns.toArray(new String[0])); int ix = 0; for (Method m : ms.values()) { wc.getField("mts" + ix++).set(null, m.getParameterTypes()); } return (Wrapper) wc.newInstance(); } catch (RuntimeException e) { throw e; } catch (Throwable e) { throw new RuntimeException(e.getMessage(), e); } finally { cc.release(); ms.clear(); mns.clear(); dmns.clear(); } } //final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass()); 会实现该类 // instance 【被代理对象】 abstract public Object invokeMethod(Object instance, String mn, Class<?>[] types, Object[] args) throws NoSuchMethodException, InvocationTargetException; }
Wrapper创建的动态代理文件 Wrapper0.class 【反编译如下】
-
Wrapper0是通过调用 Wrapper.getWrapper(DemoServiceImpl.class) 生成的类【通常在服务暴露过程中调用该方法,将所有的rpc接口实现类统一转换成Wrapper的子类】
-
Wrapper0中的每个方法内,都有将参数转成DemoServiceImpl 类型的代码行
-
在代理类class实例【如:Wrapper0】与代理类实例 创建阶段只需要传入 被代理对象的class类型;【形式参数】
-
Wrapper0#invokeMethod方法执行时需要传入 被代理对象实例 【实际参数】
-
Wrapper0 没有将被代理对象实例作为属性;而 Proxy生成代理对象有将被代理对象实例作为属性
// 与Wrapper在同一个package下 package org.apache.dubbo.common.bytecode; import java.lang.reflect.InvocationTargetException; import java.util.Map; import org.apache.dubbo.rpc.protocol.dubbo.support.CustomArgument; import org.apache.dubbo.rpc.protocol.dubbo.support.DemoServiceImpl; import org.apache.dubbo.rpc.protocol.dubbo.support.Man; import org.apache.dubbo.rpc.protocol.dubbo.support.NonSerialized; import org.apache.dubbo.rpc.protocol.dubbo.support.Person; import org.apache.dubbo.rpc.protocol.dubbo.support.Type; // 实现ClassGenerator.DC接口 表示Wrapper0是动态代理类 public class Wrapper0 extends Wrapper implements ClassGenerator.DC { public static String[] pns; public static Map pts; public static String[] mns; public static String[] dmns; public static Class[] mts0; public static Class[] mts1; public static Class[] mts2; public static Class[] mts3; public static Class[] mts4; public static Class[] mts5; public static Class[] mts6; public static Class[] mts7; public static Class[] mts8; public static Class[] mts9; public static Class[] mts10; public static Class[] mts11; public static Class[] mts12; public static Class[] mts13; public static Class[] mts14; public static Class[] mts15; public static Class[] mts16; public static Class[] mts17; public static Class[] mts18; public static Class[] mts19; public static Class[] mts20; public static Class[] mts21; public String[] getPropertyNames() { return pns; } public boolean hasProperty(String paramString) { return pts.containsKey(paramString); } public Class getPropertyType(String paramString) { return (Class)pts.get(paramString); } public String[] getMethodNames() { return mns; } public String[] getDeclaredMethodNames() { return dmns; } public void setPropertyValue(Object paramObject1, String paramString, Object paramObject2) { try { DemoServiceImpl demoServiceImpl = (DemoServiceImpl)paramObject1; } catch (Throwable throwable) { throw new IllegalArgumentException(throwable); } throw new NoSuchPropertyException("Not found property \"" + paramString + "\" field or setter method in class org.apache.dubbo.rpc.protocol.dubbo.support.DemoServiceImpl."); } public Object getPropertyValue(Object paramObject, String paramString) { DemoServiceImpl demoServiceImpl; try { demoServiceImpl = (DemoServiceImpl)paramObject; } catch (Throwable throwable) { throw new IllegalArgumentException(throwable); } if (paramString.equals("threadName")) return demoServiceImpl.getThreadName(); if (paramString.equals("remoteApplicationName")) return demoServiceImpl.getRemoteApplicationName(); throw new NoSuchPropertyException("Not found property \"" + paramString + "\" field or setter method in class org.apache.dubbo.rpc.protocol.dubbo.support.DemoServiceImpl."); } // 所有DemoService方法调用入口 public Object invokeMethod(Object paramObject, String paramString, Class[] paramArrayOfClass, Object[] paramArrayOfObject) throws InvocationTargetException { // 执行到 Wrapper.getWrapper(DemoServiceImpl.class); // Wrapper0 中所有方法内部均调用 demoServiceImpl 对应方法 DemoServiceImpl demoServiceImpl; try { demoServiceImpl = (DemoServiceImpl)paramObject; } catch (Throwable throwable) { throw new IllegalArgumentException(throwable); } // 看到这么一串if else 也有点醉了 // 下列方法名中有DemoService接口的所有方法 // 还拥有 EchoService【回声接口】,Destroyable【可销毁接口】对应方法 // AbstractProxyFactory 有添加 *EchoService, Destroyable* 的代码 try { if (!"invoke".equals(paramString) || paramArrayOfClass.length != 2) { if (!"add".equals(paramString) || paramArrayOfClass.length != 2) { if (!"get".equals(paramString) || paramArrayOfClass.length != 1) { if (!"getInt".equals(paramString) || paramArrayOfClass.length != 1) { if (!"timestamp".equals(paramString) || paramArrayOfClass.length != 0) { if (!"keys".equals(paramString) || paramArrayOfClass.length != 1) { if (!"getType".equals(paramString) || paramArrayOfClass.length != 1) { if (!"getSize".equals(paramString) || paramArrayOfClass.length != 1 || !paramArrayOfClass[0].getName().equals("[Ljava.lang.Object;")) { if (!"getSize".equals(paramString) || paramArrayOfClass.length != 1 || !paramArrayOfClass[0].getName().equals("[Ljava.lang.String;")) { if (!"getPerson".equals(paramString) || paramArrayOfClass.length != 2 || !paramArrayOfClass[0].getName().equals("org.apache.dubbo.rpc.protocol.dubbo.support.Person") || !paramArrayOfClass[1].getName().equals("org.apache.dubbo.rpc.protocol.dubbo.support.Person")) { if (!"getPerson".equals(paramString) || paramArrayOfClass.length != 1 || !paramArrayOfClass[0].getName().equals("org.apache.dubbo.rpc.protocol.dubbo.support.Man")) { if (!"getPerson".equals(paramString) || paramArrayOfClass.length != 1 || !paramArrayOfClass[0].getName().equals("org.apache.dubbo.rpc.protocol.dubbo.support.Person")) { if (!"getThreadName".equals(paramString) || paramArrayOfClass.length != 0) { if (!"echo".equals(paramString) || paramArrayOfClass.length != 1 || !paramArrayOfClass[0].getName().equals("java.lang.String")) { if (!"echo".equals(paramString) || paramArrayOfClass.length != 1 || !paramArrayOfClass[0].getName().equals("java.util.Map")) { if (!"enumlength".equals(paramString) || paramArrayOfClass.length != 1) { if (!"stringLength".equals(paramString) || paramArrayOfClass.length != 1) { if (!"sayHello".equals(paramString) || paramArrayOfClass.length != 1) { if (!"nonSerializedParameter".equals(paramString) || paramArrayOfClass.length != 1) { if (!"returnNonSerialized".equals(paramString) || paramArrayOfClass.length != 0) { if (!"getRemoteApplicationName".equals(paramString) || paramArrayOfClass.length != 0) { if (!"gerPerson".equals(paramString) || paramArrayOfClass.length != 1) throw new NoSuchMethodException("Not found method \"" + paramString + "\" in class org.apache.dubbo.rpc.protocol.dubbo.support.DemoServiceImpl."); return demoServiceImpl.gerPerson((Person)paramArrayOfObject[0]); } return demoServiceImpl.getRemoteApplicationName(); } return demoServiceImpl.returnNonSerialized(); } demoServiceImpl.nonSerializedParameter((NonSerialized)paramArrayOfObject[0]); return null; } demoServiceImpl.sayHello((String)paramArrayOfObject[0]); return null; } new Integer(); super(new Integer()); return new Integer(); } return demoServiceImpl.enumlength((Type[])paramArrayOfObject[0]); } return demoServiceImpl.echo((Map)paramArrayOfObject[0]); } return demoServiceImpl.echo((String)paramArrayOfObject[0]); } return demoServiceImpl.getThreadName(); } new Integer(); super(new Integer()); return new Integer(); } return demoServiceImpl.getPerson((Man)paramArrayOfObject[0]); } new Integer(); super(new Integer()); return new Integer(); } new Integer(); super(new Integer()); return new Integer(); } new Integer(); super(new Integer()); return new Integer(); } return demoServiceImpl.getType((Type)paramArrayOfObject[0]); } return demoServiceImpl.keys((Map)paramArrayOfObject[0]); } new Long(); super(new Long()); return new Long(); } new Integer(); super(new Integer()); return new Integer(); } return demoServiceImpl.get((CustomArgument)paramArrayOfObject[0]); } new Long(); super(new Long()); return new Long(); } return demoServiceImpl.invoke((String)paramArrayOfObject[0], (String)paramArrayOfObject[1]); } catch (Throwable throwable) { throw new InvocationTargetException(throwable); } } }
dubbo Proxy代理类创建分析
-
testDemoProtocol方法中执行protocol.refer(***) 生成Invoke对象
-
proxyFactory#getProxy --> Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
-
invoke作为被代理对象 调用proxyFactory.getProxy(invoke) 从而生成proxy对象 【通常在服务应用阶段被调用到;也有例外】
-
【注意】Proxy.getProxy(interfaces) 返回值是Proxy的子类,
-
【注意】newInstance(new InvokerInvocationHandler(invoker)); 返回值是 具体接口【interfaces】的实现类
public class DubboProtocolTest { private Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); private ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); @Test public void testDemoProtocol() throws Exception { DemoService service = new DemoServiceImpl(); int port = NetUtils.getAvailablePort(); protocol.export(proxyFactory.getInvoker(service, DemoService.class, URL.valueOf("dubbo://127.0.0.1:" + port + "/" + DemoService.class.getName() + "?codec=exchange"))); // 分析入口:服务引用阶段调用 proxyFactory#getProxy【有例外】 service = proxyFactory.getProxy(protocol.refer(DemoService.class, URL.valueOf("dubbo://127.0.0.1:" + port + "/" + DemoService.class.getName() + "?codec=exchange").addParameter("timeout", 3000L))); assertEquals(service.getSize(new String[]{"", "", ""}), 3); } 。。。 }
org.apache.dubbo.common.bytecode.Proxy
-
入口方法:Proxy#getProxy
-
Proxy 也采用Javassist生成代理对象
-
Proxy#getProxy 中有两次调用org.apache.dubbo.common.bytecode.ClassGenerator#toClass();【ccp.toClass(); 与 ccm.toClass();】
-
两次调用toClass是比较容易让读者迷惑的地方
-
注意ccp.toClass 是 org.apache.dubbo.common.bytecode.proxy0类型【小写p】
-
注意ccm.toClass 是 org.apache.dubbo.common.bytecode.Proxy0类型【大写P】
-
debug toClass 手动执行ccm.mCtc.writeFile("/doc"); ccp.mCtc.writeFile("/doc"); 可生成对应的class文件
public abstract class Proxy { private static final AtomicLong PROXY_CLASS_COUNTER = new AtomicLong(0); private static final String PACKAGE_NAME = Proxy.class.getPackage().getName(); // 代理生成缓存 private static final Map<ClassLoader, Map<String, Object>> PROXY_CACHE_MAP = new WeakHashMap<ClassLoader, Map<String, Object>>(); private static final Object PENDING_GENERATION_MARKER = new Object(); protected Proxy() { } 。。。 /** * Get proxy. * * @param ics interface class array. * @return Proxy instance. */ public static Proxy getProxy(Class<?>... ics) { return getProxy(ClassUtils.getClassLoader(Proxy.class), ics); } public static Proxy getProxy(ClassLoader cl, Class<?>... ics) { if (ics.length > MAX_PROXY_COUNT) { throw new IllegalArgumentException("interface limit exceeded"); } StringBuilder sb = new StringBuilder(); for (int i = 0; i < ics.length; i++) { 。。。 } // use interface class name list as key. String key = sb.toString(); // get cache by class loader. final Map<String, Object> cache; synchronized (PROXY_CACHE_MAP) { cache = PROXY_CACHE_MAP.computeIfAbsent(cl, k -> new HashMap<>()); } Proxy proxy = null; long id = PROXY_CLASS_COUNTER.getAndIncrement(); String pkg = null; ClassGenerator ccp = null, ccm = null; try { ccp = ClassGenerator.newInstance(cl); Set<String> worked = new HashSet<>(); List<Method> methods = new ArrayList<>(); if (pkg == null) { pkg = PACKAGE_NAME; } 。。。 // 最迷惑的一段代码 // ccp 与 ccm是啥关系【需要看看对应代码怎么写】 // ccp.toClass 是 org.apache.dubbo.common.bytecode.proxy0类型【小写p】 // ccm.toClass 是 org.apache.dubbo.common.bytecode.Proxy0类型【大写P】 // ccp只有定义,但并没有返回或被引用【乍一看】 // 实际上ccp.toClass 方法就表示 org.apache.dubbo.common.bytecode.proxy0 class已被类加载器加载 // ccm与ccp 只有 pcn 类名称字符串进行关联 【形式参数】 // ccm.toClass执行时需要检测pcn【org.apache.dubbo.common.bytecode.proxy0】是否存在 // create ProxyInstance class. String pcn = pkg + ".proxy" + id; // ccp: org.apache.dubbo.common.bytecode.proxy0 ccp.setClassName(pcn); ccp.addField("public static java.lang.reflect.Method[] methods;"); ccp.addField("private " + InvocationHandler.class.getName() + " handler;"); ccp.addConstructor(Modifier.PUBLIC, new Class<?>[]{InvocationHandler.class}, new Class<?>[0], "handler=$1;"); ccp.addDefaultConstructor(); Class<?> clazz = ccp.toClass(); clazz.getField("methods").set(null, methods.toArray(new Method[0])); // create Proxy class. String fcn = Proxy.class.getName() + id; ccm = ClassGenerator.newInstance(cl); ccm.setClassName(fcn); ccm.addDefaultConstructor(); ccm.setSuperClass(Proxy.class); ccm.addMethod("public Object newInstance(" + InvocationHandler.class.getName() + " h){ return new " + pcn + "($1); }"); Class<?> pc = ccm.toClass(); proxy = (Proxy) pc.newInstance(); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } finally { // release ClassGenerator if (ccp != null) { ccp.release(); } if (ccm != null) { ccm.release(); } synchronized (cache) { if (proxy == null) { cache.remove(key); } else { cache.put(key, new WeakReference<Proxy>(proxy)); } cache.notifyAll(); } } return proxy; } // 创建的代理类需要实现该接口 // handler:被代理对象 abstract public Object newInstance(InvocationHandler handler); }
Proxy创建的动态代理文件 Proxy0.class 【反编译如下】
-
Proxy0 是Proxy的子类,有实现抽象方法:Proxy#newInstance
-
ccm.toClass()生成Proxy0 是需要 proxy0的存在
-
个人理解:Proxy0可以看作proxy0【接口代理类】的工厂
/*******调用方代码**********/ @Override @SuppressWarnings("unchecked") public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) { // Proxy.getProxy(interfaces) 返回Proxy0【Proxy的子类】 // newInstance 则返回 proxy0 【interfaces 实现类】 return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker)); } /*****************/ // Proxy0 代码 package org.apache.dubbo.common.bytecode; import java.lang.reflect.InvocationHandler; public class Proxy0 extends Proxy implements ClassGenerator.DC { public Object newInstance(InvocationHandler paramInvocationHandler) { // 返回proxy0【interfaces 实现类】 return new proxy0(paramInvocationHandler); } }
Proxy创建的动态代理文件 proxy0.class【反编译如下】
-
proxy0 持有属性:InvocationHandler
-
InvocationHandler 持有属性:Invoker【被代理类】
-
proxy0是DemoService的实现类
-
具体方法实现:--> InvocationHandler --> Invoker
package org.apache.dubbo.common.bytecode; import com.alibaba.dubbo.rpc.service.EchoService; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.util.Map; import java.util.Set; import org.apache.dubbo.rpc.protocol.dubbo.support.CustomArgument; import org.apache.dubbo.rpc.protocol.dubbo.support.DemoService; import org.apache.dubbo.rpc.protocol.dubbo.support.Man; import org.apache.dubbo.rpc.protocol.dubbo.support.NonSerialized; import org.apache.dubbo.rpc.protocol.dubbo.support.Person; import org.apache.dubbo.rpc.protocol.dubbo.support.Type; import org.apache.dubbo.rpc.service.Destroyable; public class proxy0 implements ClassGenerator.DC, Destroyable, DemoService, EchoService { public static Method[] methods; private InvocationHandler handler; public Object $echo(Object paramObject) { Object[] arrayOfObject = new Object[1]; arrayOfObject[0] = paramObject; Object object = this.handler.invoke(this, methods[0], arrayOfObject); return (Object)object; } public void $destroy() { Object[] arrayOfObject = new Object[0]; Object object = this.handler.invoke(this, methods[1], arrayOfObject); } public Object invoke(String paramString1, String paramString2) throws Exception { Object[] arrayOfObject = new Object[2]; arrayOfObject[0] = paramString1; arrayOfObject[1] = paramString2; Object object = this.handler.invoke(this, methods[2], arrayOfObject); return (Object)object; } public long add(int paramInt, long paramLong) { Object[] arrayOfObject = new Object[2]; new Integer(); super(new Integer()); false[new Integer()] = new Integer(); new Long(); super(new Long()); true[new Long()] = new Long(); Object object = this.handler.invoke(this, methods[3], arrayOfObject); return (object == null) ? false : ((Long)object).longValue(); } public String get(CustomArgument paramCustomArgument) { Object[] arrayOfObject = new Object[1]; arrayOfObject[0] = paramCustomArgument; Object object = this.handler.invoke(this, methods[4], arrayOfObject); return (String)object; } public int getInt(int paramInt) { Object[] arrayOfObject = new Object[1]; new Integer(); super(new Integer()); false[new Integer()] = new Integer(); Object object = this.handler.invoke(this, methods[5], arrayOfObject); return (object == null) ? 0 : ((Integer)object).intValue(); } public long timestamp() { Object[] arrayOfObject = new Object[0]; Object object = this.handler.invoke(this, methods[6], arrayOfObject); return (object == null) ? false : ((Long)object).longValue(); } public Set keys(Map paramMap) { Object[] arrayOfObject = new Object[1]; arrayOfObject[0] = paramMap; Object object = this.handler.invoke(this, methods[7], arrayOfObject); return (Set)object; } public Type getType(Type paramType) { Object[] arrayOfObject = new Object[1]; arrayOfObject[0] = paramType; Object object = this.handler.invoke(this, methods[8], arrayOfObject); return (Type)object; } public int getSize(Object[] paramArrayOfObject) { Object[] arrayOfObject = new Object[1]; arrayOfObject[0] = paramArrayOfObject; Object object = this.handler.invoke(this, methods[9], arrayOfObject); return (object == null) ? 0 : ((Integer)object).intValue(); } public int getSize(String[] paramArrayOfString) { Object[] arrayOfObject = new Object[1]; arrayOfObject[0] = paramArrayOfString; Object object = this.handler.invoke(this, methods[10], arrayOfObject); return (object == null) ? 0 : ((Integer)object).intValue(); } public void sayHello(String paramString) { Object[] arrayOfObject = new Object[1]; arrayOfObject[0] = paramString; Object object = this.handler.invoke(this, methods[11], arrayOfObject); } public Map echo(Map paramMap) { Object[] arrayOfObject = new Object[1]; arrayOfObject[0] = paramMap; Object object = this.handler.invoke(this, methods[12], arrayOfObject); return (Map)object; } public String echo(String paramString) { Object[] arrayOfObject = new Object[1]; arrayOfObject[0] = paramString; Object object = this.handler.invoke(this, methods[13], arrayOfObject); return (String)object; } public Type enumlength(Type[] paramArrayOfType) { Object[] arrayOfObject = new Object[1]; arrayOfObject[0] = paramArrayOfType; Object object = this.handler.invoke(this, methods[14], arrayOfObject); return (Type)object; } public int stringLength(String paramString) { Object[] arrayOfObject = new Object[1]; arrayOfObject[0] = paramString; Object object = this.handler.invoke(this, methods[15], arrayOfObject); return (object == null) ? 0 : ((Integer)object).intValue(); } public void nonSerializedParameter(NonSerialized paramNonSerialized) { Object[] arrayOfObject = new Object[1]; arrayOfObject[0] = paramNonSerialized; Object object = this.handler.invoke(this, methods[16], arrayOfObject); } public NonSerialized returnNonSerialized() { Object[] arrayOfObject = new Object[0]; Object object = this.handler.invoke(this, methods[17], arrayOfObject); return (NonSerialized)object; } public String getRemoteApplicationName() { Object[] arrayOfObject = new Object[0]; Object object = this.handler.invoke(this, methods[18], arrayOfObject); return (String)object; } public String getPerson(Man paramMan) { Object[] arrayOfObject = new Object[1]; arrayOfObject[0] = paramMan; Object object = this.handler.invoke(this, methods[19], arrayOfObject); return (String)object; } public int getPerson(Person paramPerson1, Person paramPerson2) { Object[] arrayOfObject = new Object[2]; arrayOfObject[0] = paramPerson1; arrayOfObject[1] = paramPerson2; Object object = this.handler.invoke(this, methods[20], arrayOfObject); return (object == null) ? 0 : ((Integer)object).intValue(); } public int getPerson(Person paramPerson) { Object[] arrayOfObject = new Object[1]; arrayOfObject[0] = paramPerson; Object object = this.handler.invoke(this, methods[21], arrayOfObject); return (object == null) ? 0 : ((Integer)object).intValue(); } public String getThreadName() { Object[] arrayOfObject = new Object[0]; Object object = this.handler.invoke(this, methods[22], arrayOfObject); return (String)object; } public proxy0() {} public proxy0(InvocationHandler paramInvocationHandler) { this.handler = paramInvocationHandler; } }
Wrapper 与 Proxy差异点
- Wrapper只生成的代理类Wrapper* 【Wrapper子类】
- Proxy同时生成Proxy*【Proxy子类】,proxy*【接口实现类】
- Wrapper* 是被代理对象的代理 ,但并不持有被代理对象属性
- Proxy* 不是被代理对象的代理,但可通过 newInstance方法创建 proxy*
- proxy* 是被代理对象的代理 ,且持有被代理对象属性
- 服务调用方必须有通过Proxy创建出对应的proxy*【rpc接口实现类代理】 对象的过程;因为用户代码需要显式调用接口方法
- wrapper* 没有实现任何接口,所以不能被显式调用,通常在框架内部使用【将任何rpc接口实现类转换成统一对象】进行方法调用;【有例外】