1.SOFA RPC源码解析
1.1 RPC代理机制
在SOFA RPC中,服务引用采用代理模式把本地方法调用转换为远程服务调用,从而使开发者像使用本地Java方法一样,使用远程服务,屏蔽了底层的网络通讯细节,使开发人员把精力集中在业务开发中。
简单回顾一下代理模式,以便大家理解SOFA RPC中代理机制的实现方式。
代理模式是常用的设计模式之一。当无法直接访问某个对象或访问某个对象存在困难时,可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,所访问的真实对象与代理对象需要实现相同的接口。
按照代理的创建时期,代理类可以分为两种:
1. 静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了;
2. 动态代理:在程序运行时,运用反射机制动态创建而成。
在SOFABoot中,对于JVM服务类型的服务引用,即可以针对某个接口创建代理对象,也可以针对某个类创建代理对象。
在SOFA RPC中,规定只能针对某个接口创建代理对象,所以采用动态代理方式为远程服务创建本地代理对象。如果被代理的对象为Java类,而不是接口,则在创建代理对象时,抛出异常,例如:
1. The value of config consumer.interface[com.alipay.sofa.boot.examples.demo.rpc.bean.PersonServiceImpl2] is illegal,interfaceId must set interface class, not implement class
在SOFA RPC中,主要有两种创建代理的方式:JDK动态代理机制和Javassist动态类库。
在此补充说明一下,为了查看Proxy动态生成的代理对象的源文件,必须先导出字节码文件,然后通过反编译工具(如:jad)生成源文件。对于Proxy,导出字节码文件方式为在应用代码开始位置设置sun.misc.ProxyGenerator.saveGeneratedFiles为true:
1. @SpringBootApplication
2. @ImportResource({"classpath*:rpc-starter-example.xml" })
3. public class SofaBootRpcDemoApplication {
4.
5. public static void main(String[] args)throws InterruptedException {
6.
7. System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
8.
9. ConfigurableApplicationContext ac =SpringApplication.run(SofaBootRpcDemoApplication.class, args);
10.
11.
12. }
13. }
注意,需要在工程根目录下,增加 com/sun/proxy目录,否则会报错如下:
1. Exception in thread "main"java.lang.InternalError: I/O exception saving generatedfile:java.io.FileNotFoundException : com\sun\proxy\$Proxy0.class (系统找不到指定的路径。)
2. atsun.misc.ProxyGenerator$1.run(ProxyGenerator.java:336 )
3. atsun.misc.ProxyGenerator$1.run(ProxyGenerator.java:327 )
4. at java.security.AccessController.doPrivileged( NativeMethod)
5. atsun.misc.ProxyGenerator.generateProxyClass( ProxyGenerator.java:326)
6. atjava.lang.reflect.Proxy$ProxyClassFactory.apply( Proxy.java:672)
7. atjava.lang.reflect.Proxy$ProxyClassFactory.apply( Proxy.java:592)
8. atjava.lang.reflect.WeakCache$Factory.get( WeakCache.java:244)
9. atjava.lang.reflect.WeakCache.get(WeakCache.java:141 )
10. atjava.lang.reflect.Proxy.getProxyClass0(Proxy.java:455 )
11. atjava.lang.reflect.Proxy.newProxyInstance( Proxy.java:738)
1.1.1 JDK动态代理
提到JDK动态代理,大家一定想到java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。
1. 通过实现InvocationHandler接口,为代理对象提供调用处理器handler。当调用代理对象某个方法时,该方法调用将会被分发到handler的invoke方法,由其在调用目标对象的方法前后,进行一些额外处理。
2. 通过Proxy类newProxyInstance方法,为实现某个接口的类创建代理对象。
首先,看一下JDKProxy类的源码,该类对外提供了为指定接口动态创建代理对象的方法:
1. @Extension("jdk")
2. public class JDKProxy implements Proxy {
3.
4. @Override
5. public <T> T getProxy(Class<T>interfaceClass, Invoker proxyInvoker) {
6. InvocationHandler handler = new JDKInvocationHandler(interfaceClass,proxyInvoker);
7. ClassLoader classLoader =ClassLoaderUtils.getCurrentClassLoader();
8. T result = (T)java.lang.reflect.Proxy.newProxyInstance(classLoader,
9. new Class[] { interfaceClass },handler);
10. return result;
11. }
12.
13. @Override
14. public Invoker getInvoker(ObjectproxyObject) {
15. return parseInvoker(proxyObject);
16. }
17.
18. /**
19. * Parse proxy invoker from proxy object
20. *
21. * @param proxyObject Proxy object
22. * @return proxy invoker
23. */
24. public static Invoker parseInvoker(ObjectproxyObject) {
25. InvocationHandler handler =java.lang.reflect.Proxy.getInvocationHandler(proxyObject);
26. if (handler instanceofJDKInvocationHandler) {
27. return ((JDKInvocationHandler)handler).getProxyInvoker();
28. }
29. return null;
30. }
31. }
getProxy方法主要处理逻辑如下:
1. 根据接口类型和Invoker接口的实现类,创建JDKInvocationHandler实例;
2. 调用Proxy类newProxyInstance方法,创建代理对象;
在SOFA RPC中,com.alipay.sofa.rpc.proxy.jdk.JDKInvocationHandler类实现了InvocationHandler接口。
JDKInvocationHandler类的源代码如下:
1. public class JDKInvocationHandlerimplements InvocationHandler {
2.
3. /**
4. * 代理类
5. */
6. private Class proxyClass;
7.
8. /**
9. * 代理调用器
10. */
11. private Invoker proxyInvoker;
12.
13. /**
14. * Instantiates a new Jdk invocationhandler.
15. *
16. * @param proxyClass the proxy class
17. * @param proxyInvoker the proxy invoker
18. */
19. public JDKInvocationHandler(ClassproxyClass, Invoker proxyInvoker) {
20. this.proxyClass = proxyClass;
21. this.proxyInvoker = proxyInvoker;
22. }
23.
24. @Override
25. public Object invoke(Object proxy, Methodmethod, Object[] paramValues)
26. throws Throwable {
27. String methodName = method.getName();
28. Class[] paramTypes =method.getParameterTypes();
29. if("toString".equals(methodName) && paramTypes.length == 0) {
30. return proxyInvoker.toString();
31. } else if("hashCode".equals(methodName) && paramTypes.length == 0) {
32. return proxyInvoker.hashCode();
33. } else if("equals".equals(methodName) && paramTypes.length == 1) {
34. Object another = paramValues[0];
35. return proxy == another ||
36. (proxy.getClass().isInstance(another)&& proxyInvoker.equals(JDKProxy.parseInvoker(another)));
37. }
38. SofaRequest sofaRequest =MessageBuilder.buildSofaRequest(method.getDeclaringClass(),
39. method, paramTypes, paramValues);
40. SofaResponse response =proxyInvoker.invoke(sofaRequest);
41. if (response.isError()) {
42. throw newSofaRpcException(RpcErrorType.SERVER_UNDECLARED_ERROR, response.getErrorMsg());
43. }
44. Object ret = response.getAppResponse();
45. if (ret instanceof Throwable) {
46. throw (Throwable) ret;
47. } else {
48. if (ret == null) {
49. returnClassUtils.getDefaultArg(method.getReturnType());
50. }
51. return ret;
52. }
53. }
54.
55. /**
56. * Gets proxy class.
57. *
58. * @return the proxy class
59. */
60. public Class getProxyClass() {
61. return proxyClass;
62. }
63.
64. /**
65. * Gets proxy invoker.
66. *
67. * @return the proxy invoker
68. */
69. public Invoker getProxyInvoker() {
70. return proxyInvoker;
71. }
72. }
JDKInvocationHandler类invoke方法主要处理逻辑如下:
1. 本地方法调用封装成SofaRequest请求对象;
2. 通过Invoker接口实现类提供的各种远程服务调用方式,以SofaRequest为参数,进行远程服务调用,并返回处理结果SofaResponse。
3. 从SofaResponse对象中获取实际的远程服务的处理结果,并返回给本地客户端。
在此,以SOFABoot自带的RPC案例sofaboot-sample-with-rpc为例,看看为com.alipay.sofa.boot.examples.demo.rpc.bean.PersonService接口创建的服务代理对象的源文件:
1. importcom.alipay.sofa.boot.examples.demo.rpc.bean.PersonService;
2. importjava.lang.reflect.InvocationHandler;
3. import java.lang.reflect.Method;
4. import java.lang.reflect.Proxy;
5. importjava.lang.reflect.UndeclaredThrowableException;
6.
7. public final class $Proxy0 extendsProxy implements PersonService
8. {
9. private static Method m1;
10. private static Method m3;
11. private static Method m0;
12. private static Method m2;
13.
14. public $Proxy0(InvocationHandlerparamInvocationHandler)
15. throws
16. {
17. super(paramInvocationHandler);
18. }
19.
20. public final boolean equals(ObjectparamObject)
21. throws
22. {
23. try
24. {
25. return ((Boolean)this.h.invoke(this, m1,new Object[] { paramObject })).booleanValue();
26. }
27. catch (RuntimeExceptionlocalRuntimeException)
28. {
29. throw localRuntimeException;
30. }
31. catch (Throwable localThrowable)
32. {
33. }
34. throw newUndeclaredThrowableException(localThrowable);
35. }
36.
37. publicfinal String sayName(String paramString)
38. throws
39. {
40. try
41. {
42. return (String)this.h.invoke(this, m3,new Object[] { paramString });
43. }
44. catch (RuntimeExceptionlocalRuntimeException)
45. {
46. throw localRuntimeException;
47. }
48. catch (Throwable localThrowable)
49. {
50. }
51. throw newUndeclaredThrowableException(localThrowable);
52. }
53.
54. public final int hashCode()
55. throws
56. {
57. try
58. {
59. return ((Integer)this.h.invoke(this, m0,null)).intValue();
60. }
61. catch (RuntimeExceptionlocalRuntimeException)
62. {
63. throw localRuntimeException;
64. }
65. catch (Throwable localThrowable)
66. {
67. }
68. throw newUndeclaredThrowableException(localThrowable);
69. }
70.
71. public final String toString()
72. throws
73. {
74. try
75. {
76. return (String)this.h.invoke(this, m2,null);
77. }
78. catch (RuntimeException localRuntimeException)
79. {
80. throw localRuntimeException;
81. }
82. catch (Throwable localThrowable)
83. {
84. }
85. throw newUndeclaredThrowableException(localThrowable);
86. }
87.
88. static
89. {
90. try
91. {
92. m1 =Class.forName("java.lang.Object").getMethod("equals", newClass[] { Class.forName("java.lang.Object") });
93. m3 =Class.forName("com.alipay.sofa.boot.examples.demo.rpc.bean.PersonService").getMethod("sayName",new Class[] { Class.forName("java.lang.String") });
94. m0 = Class.forName("java.lang.Object").getMethod("hashCode",new Class[0]);
95. m2 =Class.forName("java.lang.Object").getMethod("toString", newClass[0]);
96. return;
97. }
98. catch (NoSuchMethodExceptionlocalNoSuchMethodException)
99. {
100. throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
101. }
102. catch (ClassNotFoundExceptionlocalClassNotFoundException)
103. {
104. }
105. throw newNoClassDefFoundError(localClassNotFoundException.getMessage());
106. }
107. }
从上述代码可以看出,该代理对象继承了Proxy类,实现了PersonService接口。主要看一下代理对象对于PersonService接口的sayName方法实现方式。在sayName方法中,实际调用handler的invoke方法:
1. (String)this.h.invoke(this, m3, newObject[] { paramString })
此处h为JDKInvocationHandler实例。
这样,当客户端调用实现了PersonService接口的代理对象的sayName方法时,实际上是调用JDKInvocationHandler类invoke方法,完成本地方法调用到远程服务调用的转换。JDKInvocationHandler类invoke方法的主要处理逻辑如上所述。
1.1.2 Javassist动态类库
在SOFA RPC中,提供了另一种为远程服务创建本地代理对象的方式,即Javassist动态类库。
Javassist是一款字节码编辑工具,可以直接编辑和生成Java字节码,以达到对.class文件进行动态修改的效果。关于Javassist,在此不详述,有兴趣的同学可以在网上搜索资料自行研究。
首先,看一下JavassistProxy类的源码,该类对外提供了为指定接口动态创建代理对象的方法:
1. @Extension("javassist")
2. public class JavassistProxy implementsProxy {
3.
4. /**
5. * Logger for this class
6. */
7. private static final Logger LOGGER =LoggerFactory.getLogger(JavassistProxy.class);
8.
9. private static AtomicInteger counter = new AtomicInteger();
10.
11. /**
12. * 原始类和代理类的映射
13. */
14. protected final static Map<Class,Class> PROXY_CLASS_MAP = new ConcurrentHashMap<Class, Class>();
15.
16. @Override
17. @SuppressWarnings("unchecked")
18. public <T> T getProxy(Class<T>interfaceClass, Invoker proxyInvoker) {
19. try {
20. Class clazz =PROXY_CLASS_MAP.get(interfaceClass);
21. if (clazz == null) {
22. //生成代理类
23. String interfaceName =ClassTypeUtils.getTypeStr(interfaceClass);
24. ClassPool mPool =ClassPool.getDefault();
25. mPool.appendClassPath(newLoaderClassPath(ClassLoaderUtils.getClassLoader(JavassistProxy.class)));
26. CtClass mCtc =mPool.makeClass(interfaceName + "_proxy_" +counter.getAndIncrement());
27. if(interfaceClass.isInterface()) {
28. mCtc.addInterface(mPool.get(interfaceName));
29. } else {
30. throw newIllegalArgumentException(interfaceClass.getName() + " is not aninterface");
31. }
32.
33. // 继承 java.lang.reflect.Proxy
34. mCtc.setSuperclass(mPool.get(java.lang.reflect.Proxy.class.getName()));
35. CtConstructor constructor = newCtConstructor(null, mCtc);
36. constructor.setModifiers(Modifier.PUBLIC);
37. constructor.setBody("{super(new" + UselessInvocationHandler.class.getName() + "());}");
38. mCtc.addConstructor(constructor);
39.
40. mCtc.addField(CtField.make("public" + Invoker.class.getCanonicalName() + " proxyInvoker = null;",
41. mCtc));
42. StringBuilder sb = null;
43. if (LOGGER.isDebugEnabled()) {
44. sb = new StringBuilder();
45. }
46. List<String> methodList =createMethod(interfaceClass);
47. for (String methodStr :methodList) {
48. mCtc.addMethod(CtMethod.make(methodStr,mCtc));
49. if(LOGGER.isDebugEnabled()) {
50. sb.append(methodStr).append("\n");
51. }
52. }
53. if (LOGGER.isDebugEnabled()) {
54. LOGGER.debug("javassistproxy of interface: {} \r\n{}", interfaceClass,
55. sb != null ?sb.toString() : "");
56. }
57. clazz = mCtc.toClass();
58. PROXY_CLASS_MAP.put(interfaceClass,clazz);
59. }
60. Object instance =clazz.newInstance();
61. clazz.getField("proxyInvoker").set(instance,proxyInvoker);
62. return (T) instance;
63. } catch (Exception e) {
64. throw newSofaRpcRuntimeException("", e);
65. }
66. }
67.
68. private List<String>createMethod(Class<?> interfaceClass) {
69. Method[] methodAry =interfaceClass.getMethods();
70. StringBuilder sb = newStringBuilder(512);
71. List<String> resultList = newArrayList<String>();
72. for (Method m : methodAry) {
73. if(Modifier.isNative(m.getModifiers()) || Modifier.isFinal(m.getModifiers())) {
74. continue;
75. }
76. Class<?>[] mType =m.getParameterTypes();
77. Class<?> returnType =m.getReturnType();
78.
79. sb.append(Modifier.toString(m.getModifiers()).replace("abstract","") + " " +
80. ClassTypeUtils.getTypeStr(returnType)+ " " + m.getName() + "( ");
81. int c = 0;
82.
83. for (Class<?> mp : mType) {
84. sb.append(" " +mp.getCanonicalName() + " arg" + c + " ,");
85. c++;
86. }
87. sb.deleteCharAt(sb.length() - 1);
88. sb.append(")");
89. Class<?>[] exceptions =m.getExceptionTypes();
90. if (exceptions.length > 0) {
91. sb.append(" throws");
92. for (Class<?> exception :exceptions) {
93. sb.append(exception.getCanonicalName()+ " ,");
94. }
95. sb =sb.deleteCharAt(sb.length() - 1);
96. }
97. sb.append("{");
98.
99. sb.append(" Class clazz =" + interfaceClass.getCanonicalName() + ".class;");
100. sb.append(" String methodName= \"" + m.getName() + "\";");
101. sb.append(" Class[] paramTypes= new Class[" + c + "];");
102. sb.append(" Object[]paramValues = new Object[" + c + "];");
103. for (int i = 0; i < c; i++) {
104. sb.append("paramValues["+ i + "] = ($w)$" + (i + 1) + ";");
105. sb.append("paramTypes["+ i + "] = " + mType[i].getCanonicalName() + ".class;");
106. }
107.
108. sb.append(SofaRequest.class.getCanonicalName()+ " request = " +
109. MessageBuilder.class.getCanonicalName()+
110. ".buildSofaRequest(clazz,methodName, paramTypes, paramValues);");
111. sb.append(SofaResponse.class.getCanonicalName()+ " response = " +
112. "proxyInvoker.invoke(request);");
113. sb.append("if(response.isError()){");
114. sb.append(" throw new " +SofaRpcException.class.getName() + "(" + RpcErrorType.class.getName()+
115. ".SERVER_UNDECLARED_ERROR,"+
116. "response.getErrorMsg());");
117. sb.append("}");
118.
119. if (returnType.equals(void.class)){
120. sb.append("return;");
121. } else {
122. sb.append("Object ret =response.getAppResponse();");
123. sb.append("if(retinstanceof " + Throwable.class.getName() + ") {");
124. sb.append(" throw (" + Throwable.class.getName() +") ret;");
125. sb.append("} else{");
126. sb.append(" return " + asArgument(returnType,"ret") + ";");
127. sb.append("}");
128. }
129.
130. sb.append("}");
131. resultList.add(sb.toString());
132. sb.delete(0, sb.length());
133. }
134.
135. // toString()
136. sb.append("public StringtoString() {");
137. sb.append(" return proxyInvoker.toString();");
138. sb.append("}");
139. resultList.add(sb.toString());
140. // hashCode()
141. sb.delete(0, sb.length());
142. sb.append("public int hashCode(){");
143. sb.append(" return proxyInvoker.hashCode();");
144. sb.append("}");
145. resultList.add(sb.toString());
146. // equals()
147. sb.delete(0, sb.length());
148. sb.append("public booleanequals(Object obj) {");
149. sb.append(" return this == obj ||(getClass().isInstance($1) " +
150. "&&proxyInvoker.equals(" + JavassistProxy.class.getName() +".parseInvoker($1)));");
151. sb.append("}");
152. resultList.add(sb.toString());
153. return resultList;
154. }
155.
156. private String asArgument(Class<?>cl, String name) {
157. if (cl.isPrimitive()) {
158. if (Boolean.TYPE == cl) {
159. return name +"==null?false:((Boolean)" + name + ").booleanValue()";
160. }
161. if (Byte.TYPE == cl) {
162. return name +"==null?(byte)0:((Byte)" + name + ").byteValue()";
163. }
164. if (Character.TYPE == cl) {
165. return name +"==null?(char)0:((Character)" + name + ").charValue()";
166. }
167. if (Double.TYPE == cl) {
168. return name +"==null?(double)0:((Double)" + name + ").doubleValue()";
169. }
170. if (Float.TYPE == cl) {
171. return name +"==null?(float)0:((Float)" + name + ").floatValue()";
172. }
173. if (Integer.TYPE == cl) {
174. return name +"==null?(int)0:((Integer)" + name + ").intValue()";
175. }
176. if (Long.TYPE == cl) {
177. return name +"==null?(long)0:((Long)" + name + ").longValue()";
178. }
179. if (Short.TYPE == cl) {
180. return name +"==null?(short)0:((Short)" + name + ").shortValue()";
181. }
182. throw new RuntimeException(name +" is unknown primitive type.");
183. }
184. return "(" +ClassTypeUtils.getTypeStr(cl) + ")" + name;
185. }
186.
187. @Override
188. public Invoker getInvoker(ObjectproxyObject) {
189. return parseInvoker(proxyObject);
190. }
191.
192. /**
193. * Parse proxy invoker from proxy object
194. *
195. * @param proxyObject Proxy object
196. * @return proxy invoker
197. */
198. public static Invoker parseInvoker(ObjectproxyObject) {
199. Field field;
200. try {
201. field =proxyObject.getClass().getField("proxyInvoker");
202. if (field != null) {
203. if (!field.isAccessible()) {
204. field.setAccessible(true);
205. }
206. return (Invoker)field.get(proxyObject);
207. } else {
208. return null;
209. }
210. } catch (Exception e) {
211. return null;
212. }
213. }
214. }
如上所示,在getProxy方法中,通过Javassist相关的API,根据接口类型和Invoker接口的实现类,动态创建代理对象的Java类文件,并编译成字节码格式的class文件。
在此,还是以SOFABoot自带的RPC案例sofaboot-sample-with-rpc为例,看看为com.alipay.sofa.boot.examples.demo.rpc.bean.PersonService接口创建的服务代理对象的源文件:
1. import com.alipay.sofa.rpc.core.exception.SofaRpcException;
2. importcom.alipay.sofa.rpc.core.request.SofaRequest;
3. importcom.alipay.sofa.rpc.core.response.SofaResponse;
4. import com.alipay.sofa.rpc.invoke.Invoker;
5. importcom.alipay.sofa.rpc.message.MessageBuilder;
6. import com.alipay.sofa.rpc.proxy.javassist.JavassistProxy;
7. importcom.alipay.sofa.rpc.proxy.javassist.UselessInvocationHandler;
8. import java.lang.reflect.Proxy;
9.
10. public class PersonService_proxy_0 extendsProxy
11. implements PersonService
12. {
13. public Invoker proxyInvoker = null;
14.
15. publicPersonService_proxy_0()
16. {
17. super(new UselessInvocationHandler());
18. }
19.
20. public String sayName(String paramString)
21. {
22. PersonService localPersonService =PersonService.class;
23. String str = "sayName";
24. Class[] arrayOfClass = new Class[1];
25. Object[] arrayOfObject = new Object[1];
26. arrayOfObject[0] = paramString;
27. arrayOfClass[0] = String.class;
28. SofaRequest localSofaRequest =MessageBuilder.buildSofaRequest(localPersonService, str, arrayOfClass,arrayOfObject);
29. SofaResponse localSofaResponse =this.proxyInvoker.invoke(localSofaRequest);
30. if (localSofaResponse.isError())
31. throw new SofaRpcException(199,localSofaResponse.getErrorMsg());
32. Object localObject =localSofaResponse.getAppResponse();
33. if ((localObject instanceof Throwable))
34. throw ((Throwable)localObject);
35. return (String)localObject;
36. }
37.
38. public String toString()
39. {
40. return this.proxyInvoker.toString();
41. }
42.
43. public int hashCode()
44. {
45. return this.proxyInvoker.hashCode();
46. }
47.
48. public boolean equals(Object paramObject)
49. {
50. if ((this == paramObject) ||((!getClass().isInstance(paramObject)) ||(this.proxyInvoker.equals(JavassistProxy.parseInvoker(paramObject)))))
51. break label42;
52. tmpTernaryOp = false;
53. label42: return true;
54. }
55. }
从上述代码可以看出,该代理对象继承了Proxy类,实现了PersonService接口。主要看一下代理对象对于PersonService接口的sayName方法实现方式。
在sayName方法中,主要处理逻辑如下:
1. 本地方法调用封装成SofaRequest请求对象;
2. 通过Invoker接口实现类提供的各种远程服务调用方式,以SofaRequest为参数,进行远程服务调用,并返回处理结果SofaResponse。
3. 从SofaResponse对象中获取实际的远程服务的处理结果,并返回给本地客户端。
这样,当客户端调用实现了PersonService接口的代理对象的sayName方法时,实际上是调用JDKInvocationHandler类invoke方法,完成本地方法调用到远程服务调用的转换。
1.1.3 总结
通过比较JDK Proxy创建的代理对象和Javassist创建的代理对象的源码可以看出,其内部实现方式有些不同:
1. 对于equals、hashCode、toString方法,JDK Proxy创建的代理对象通过反射机制调用java.lang.Object对象的equals、hashCode、toString方法;而Javassist创建的代理对象则直接调用proxyInvoker的equals、hashCode、toString方法;