1.SOFABoot源码解析
1.1 JVM服务代理机制
在SOFABoot中,采用AOP代理方式为JVM服务引用创建本地代理对象。对于AOP代理,主要有两种实现方式:
1. 针对实现接口的类,采用JDK动态代理机制;
2. 针对没有实现接口的类,采用CGLIB动态代理机制;
在SOFABoot中,对于JVM服务类型的服务引用,即可以针对某个接口创建代理对象,也可以针对某个类创建代理对象。
1.1.1 AOP代理之JDK动态代理
针对接口(例如:com.alipay.sofa.boot.examples.demo.rpc.bean.PersonService接口),为其创建JVM服务的AOP代理对象的主要逻辑如下:
1. 创建handler,此处为ServiceProxy抽象类的子类JvmServiceInvoker的实例。该类继承了ServiceProxy,而ServiceProxy实现了org.aopalliance.intercept.MethodInterceptor接口,表示此处创建AOP代理的方法拦截器。该AOP代理拦截器拦截对proxyClass指定的接口(例如: PersonService)的方法调用。
2. 创建AOP代理工厂类org.springframework.aop.framework.ProxyFactory的实例factory;
3. 配置factory:如果javaClass为接口,则factory的interfaces列表中增加javaClass。否则,设置factory的targetClass为javaClass,proxyTarget为true。
4. 把指定的AOP advice实例handler增加到advice链尾部。
5. 调用factory的getProxy方法,为指定服务创建AOP代理对象。由于此处目标类是接口,则使用JDK动态代理技术。Spring使用JDK来生成代理对象,具体的实现代码放在org.springframework.aop.framework.JdkDynamicAopProxy这个类中。JdkDynamicAopProxy 同时实现了AopProxy和InvocationHandler接口,InvocationHandler是JDK动态代理的核心,生成的代理对象的方法调用都会委托到InvocationHandler.invoke()方法。invoke主流程可以简述为:获取可以应用到此方法上的通知链(InterceptorChain),如果有,则应用通知,并执行joinpoint;如果通知链为空,则直接反射执行joinpoint。
以上是使用JDK动态代理机制动态创建JVM服务的AOP代理对象的主要流程。
为了查看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. atjava.security.AccessController.doPrivileged( Native Method)
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. at java.lang.reflect.Proxy.getProxyClass0(Proxy.java:455 )
11. atjava.lang.reflect.Proxy.newProxyInstance( Proxy.java:738)
以下为PersonService接口的AOP代理对象的源文件:
1. package com.sun.proxy;
2.
3. importcom.alipay.sofa.boot.examples.demo.rpc.bean.PersonService;
4. import java.lang.reflect.InvocationHandler;
5. import java.lang.reflect.Method;
6. import java.lang.reflect.Proxy;
7. importjava.lang.reflect.UndeclaredThrowableException;
8. import org.aopalliance.aop.Advice;
9. import org.springframework.aop.Advisor;
10. import org.springframework.aop.SpringProxy;
11. importorg.springframework.aop.TargetSource;
12. importorg.springframework.aop.framework.Advised;
13. importorg.springframework.aop.framework.AopConfigException;
14. importorg.springframework.core.DecoratingProxy;
15.
16. public final class $Proxy50 extends Proxy
17. implementsPersonService, SpringProxy, Advised, DecoratingProxy
18. {
19. private static Method m19;
20. private static Method m15;
21. private static Method m27;
22. private static Method m6;
23. private static Method m2;
24. private static Method m25;
25. private static Method m24;
26. private static Method m11;
27. private static Method m4;
28. private static Method m26;
29. private static Method m8;
30. private static Method m22;
31. private static Method m20;
32. private static Method m21;
33. private static Method m16;
34. private static Method m9;
35. private static Method m23;
36. private static Method m5;
37. private static Method m12;
38. private static Method m13;
39. private static Method m1;
40. private static Method m18;
41. private static Method m10;
42. private static Method m17;
43. private static Method m3;
44. private static Method m0;
45. private static Method m7;
46. private static Method m14;
47.
48. public $Proxy50(InvocationHandlerparamInvocationHandler)
49. throws
50. {
51. super(paramInvocationHandler);
52. }
53.
54. public final boolean isPreFiltered()
55. throws
56. {
57. try
58. {
59. return ((Boolean)this.h.invoke(this, m19,null)).booleanValue();
60. }
61. catch (RuntimeExceptionlocalRuntimeException)
62. {
63. throw localRuntimeException;
64. }
65. catch (Throwable localThrowable)
66. {
67. }
68. throw newUndeclaredThrowableException(localThrowable);
69. }
70.
71. public final boolean isProxyTargetClass()
72. throws
73. {
74. try
75. {
76. return ((Boolean)this.h.invoke(this, m15,null)).booleanValue();
77. }
78. catch (RuntimeException localRuntimeException)
79. {
80. throw localRuntimeException;
81. }
82. catch (Throwable localThrowable)
83. {
84. }
85. throw newUndeclaredThrowableException(localThrowable);
86. }
87.
88. public final Class getDecoratedClass()
89. throws
90. {
91. try
92. {
93. return (Class)this.h.invoke(this, m27,null);
94. }
95. catch (RuntimeExceptionlocalRuntimeException)
96. {
97. throw localRuntimeException;
98. }
99. catch (Throwable localThrowable)
100. {
101. }
102. throw newUndeclaredThrowableException(localThrowable);
103. }
104.
105. public final boolean isFrozen()
106. throws
107. {
108. try
109. {
110. return ((Boolean)this.h.invoke(this, m6,null)).booleanValue();
111. }
112. catch (RuntimeExceptionlocalRuntimeException)
113. {
114. throw localRuntimeException;
115. }
116. catch (Throwable localThrowable)
117. {
118. }
119. throw newUndeclaredThrowableException(localThrowable);
120. }
121.
122. public final String toString()
123. throws
124. {
125. try
126. {
127. return (String)this.h.invoke(this, m2,null);
128. }
129. catch (RuntimeException localRuntimeException)
130. {
131. throw localRuntimeException;
132. }
133. catch (Throwable localThrowable)
134. {
135. }
136. throw newUndeclaredThrowableException(localThrowable);
137. }
138.
139. public final boolean removeAdvice(AdviceparamAdvice)
140. throws
141. {
142. try
143. {
144. return ((Boolean)this.h.invoke(this, m25,new Object[] { paramAdvice })).booleanValue();
145. }
146. catch (RuntimeExceptionlocalRuntimeException)
147. {
148. throw localRuntimeException;
149. }
150. catch (Throwable localThrowable)
151. {
152. }
153. throw newUndeclaredThrowableException(localThrowable);
154. }
155.
156. public final boolean removeAdvisor(AdvisorparamAdvisor)
157. throws
158. {
159. try
160. {
161. return ((Boolean)this.h.invoke(this, m24,new Object[] { paramAdvisor })).booleanValue();
162. }
163. catch (RuntimeExceptionlocalRuntimeException)
164. {
165. throw localRuntimeException;
166. }
167. catch (Throwable localThrowable)
168. {
169. }
170. throw newUndeclaredThrowableException(localThrowable);
171. }
172.
173. public final void setExposeProxy(booleanparamBoolean)
174. throws
175. {
176. try
177. {
178. this.h.invoke(this, m11, new Object[] {Boolean.valueOf(paramBoolean) });
179. return;
180. }
181. catch (RuntimeExceptionlocalRuntimeException)
182. {
183. throw localRuntimeException;
184. }
185. catch (Throwable localThrowable)
186. {
187. }
188. throw newUndeclaredThrowableException(localThrowable);
189. }
190.
191. public final int indexOf(AdvisorparamAdvisor)
192. throws
193. {
194. try
195. {
196. return ((Integer)this.h.invoke(this, m4,new Object[] { paramAdvisor })).intValue();
197. }
198. catch (RuntimeExceptionlocalRuntimeException)
199. {
200. throw localRuntimeException;
201. }
202. catch (Throwable localThrowable)
203. {
204. }
205. throw newUndeclaredThrowableException(localThrowable);
206. }
207.
208. public final Class getTargetClass()
209. throws
210. {
211. try
212. {
213. return (Class)this.h.invoke(this, m26,null);
214. }
215. catch (RuntimeExceptionlocalRuntimeException)
216. {
217. throw localRuntimeException;
218. }
219. catch (Throwable localThrowable)
220. {
221. }
222. throw new UndeclaredThrowableException(localThrowable);
223. }
224.
225. public final TargetSource getTargetSource()
226. throws
227. {
228. try
229. {
230. return (TargetSource)this.h.invoke(this,m8, null);
231. }
232. catch (RuntimeExceptionlocalRuntimeException)
233. {
234. throw localRuntimeException;
235. }
236. catch (Throwable localThrowable)
237. {
238. }
239. throw newUndeclaredThrowableException(localThrowable);
240. }
241.
242. public final void addAdvisor(int paramInt,Advisor paramAdvisor)
243. throws AopConfigException
244. {
245. try
246. {
247. this.h.invoke(this, m22, new Object[] {Integer.valueOf(paramInt), paramAdvisor });
248. return;
249. }
250. catch (RuntimeExceptionlocalRuntimeException)
251. {
252. throw localRuntimeException;
253. }
254. catch (Throwable localThrowable)
255. {
256. }
257. throw newUndeclaredThrowableException(localThrowable);
258. }
259.
260. public final boolean isExposeProxy()
261. throws
262. {
263. try
264. {
265. return ((Boolean)this.h.invoke(this, m20,null)).booleanValue();
266. }
267. catch (RuntimeException localRuntimeException)
268. {
269. throw localRuntimeException;
270. }
271. catch (Throwable localThrowable)
272. {
273. }
274. throw newUndeclaredThrowableException(localThrowable);
275. }
276.
277. public final void addAdvisor(AdvisorparamAdvisor)
278. throws AopConfigException
279. {
280. try
281. {
282. this.h.invoke(this, m21, new Object[] {paramAdvisor });
283. return;
284. }
285. catch (RuntimeExceptionlocalRuntimeException)
286. {
287. throw localRuntimeException;
288. }
289. catch (Throwable localThrowable)
290. {
291. }
292. throw newUndeclaredThrowableException(localThrowable);
293. }
294.
295. public final void addAdvice(int paramInt,Advice paramAdvice)
296. throws AopConfigException
297. {
298. try
299. {
300. this.h.invoke(this, m16, new Object[] {Integer.valueOf(paramInt), paramAdvice });
301. return;
302. }
303. catch (RuntimeExceptionlocalRuntimeException)
304. {
305. throw localRuntimeException;
306. }
307. catch (Throwable localThrowable)
308. {
309. }
310. throw newUndeclaredThrowableException(localThrowable);
311. }
312.
313. public final Class[] getProxiedInterfaces()
314. throws
315. {
316. try
317. {
318. return (Class[])this.h.invoke(this, m9,null);
319. }
320. catch (RuntimeExceptionlocalRuntimeException)
321. {
322. throw localRuntimeException;
323. }
324. catch (Throwable localThrowable)
325. {
326. }
327. throw newUndeclaredThrowableException(localThrowable);
328. }
329.
330. public final void removeAdvisor(int paramInt)
331. throws AopConfigException
332. {
333. try
334. {
335. this.h.invoke(this, m23, new Object[] {Integer.valueOf(paramInt) });
336. return;
337. }
338. catch (RuntimeExceptionlocalRuntimeException)
339. {
340. throw localRuntimeException;
341. }
342. catch (Throwable localThrowable)
343. {
344. }
345. throw newUndeclaredThrowableException(localThrowable);
346. }
347.
348. public final int indexOf(Advice paramAdvice)
349. throws
350. {
351. try
352. {
353. return ((Integer)this.h.invoke(this, m5,new Object[] { paramAdvice })).intValue();
354. }
355. catch (RuntimeExceptionlocalRuntimeException)
356. {
357. throw localRuntimeException;
358. }
359. catch (Throwable localThrowable)
360. {
361. }
362. throw newUndeclaredThrowableException(localThrowable);
363. }
364.
365. public final void setPreFiltered(booleanparamBoolean)
366. throws
367. {
368. try
369. {
370. this.h.invoke(this, m12, new Object[] {Boolean.valueOf(paramBoolean) });
371. return;
372. }
373. catch (RuntimeExceptionlocalRuntimeException)
374. {
375. throw localRuntimeException;
376. }
377. catch (Throwable localThrowable)
378. {
379. }
380. throw newUndeclaredThrowableException(localThrowable);
381. }
382.
383. public final boolean replaceAdvisor(AdvisorparamAdvisor1, Advisor paramAdvisor2)
384. throws AopConfigException
385. {
386. try
387. {
388. return ((Boolean)this.h.invoke(this, m13,new Object[] { paramAdvisor1, paramAdvisor2 })).booleanValue();
389. }
390. catch (RuntimeException localRuntimeException)
391. {
392. throw localRuntimeException;
393. }
394. catch (Throwable localThrowable)
395. {
396. }
397. throw newUndeclaredThrowableException(localThrowable);
398. }
399.
400. public final boolean equals(ObjectparamObject)
401. throws
402. {
403. try
404. {
405. return ((Boolean)this.h.invoke(this, m1,new Object[] { paramObject })).booleanValue();
406. }
407. catch (RuntimeExceptionlocalRuntimeException)
408. {
409. throw localRuntimeException;
410. }
411. catch (Throwable localThrowable)
412. {
413. }
414. throw newUndeclaredThrowableException(localThrowable);
415. }
416.
417. public final Advisor[] getAdvisors()
418. throws
419. {
420. try
421. {
422. return (Advisor[])this.h.invoke(this,m18, null);
423. }
424. catch (RuntimeExceptionlocalRuntimeException)
425. {
426. throw localRuntimeException;
427. }
428. catch (Throwable localThrowable)
429. {
430. }
431. throw newUndeclaredThrowableException(localThrowable);
432. }
433.
434. public final boolean isInterfaceProxied(ClassparamClass)
435. throws
436. {
437. try
438. {
439. return ((Boolean)this.h.invoke(this, m10,new Object[] { paramClass })).booleanValue();
440. }
441. catch (RuntimeExceptionlocalRuntimeException)
442. {
443. throw localRuntimeException;
444. }
445. catch (Throwable localThrowable)
446. {
447. }
448. throw new UndeclaredThrowableException(localThrowable);
449. }
450.
451. public final void addAdvice(AdviceparamAdvice)
452. throws AopConfigException
453. {
454. try
455. {
456. this.h.invoke(this, m17, new Object[] {paramAdvice });
457. return;
458. }
459. catch (RuntimeException localRuntimeException)
460. {
461. throw localRuntimeException;
462. }
463. catch (Throwable localThrowable)
464. {
465. }
466. throw newUndeclaredThrowableException(localThrowable);
467. }
468.
469. publicfinal String sayName(String paramString)
470. throws
471. {
472. try
473. {
474. return (String)this.h.invoke(this, m3,new Object[] { paramString });
475. }
476. catch (RuntimeExceptionlocalRuntimeException)
477. {
478. throw localRuntimeException;
479. }
480. catch (Throwable localThrowable)
481. {
482. }
483. throw new UndeclaredThrowableException(localThrowable);
484. }
485.
486. public final int hashCode()
487. throws
488. {
489. try
490. {
491. return ((Integer)this.h.invoke(this, m0,null)).intValue();
492. }
493. catch (RuntimeExceptionlocalRuntimeException)
494. {
495. throw localRuntimeException;
496. }
497. catch (Throwable localThrowable)
498. {
499. }
500. throw newUndeclaredThrowableException(localThrowable);
501. }
502.
503. public final voidsetTargetSource(TargetSource paramTargetSource)
504. throws
505. {
506. try
507. {
508. this.h.invoke(this, m7, new Object[] {paramTargetSource });
509. return;
510. }
511. catch (RuntimeExceptionlocalRuntimeException)
512. {
513. throw localRuntimeException;
514. }
515. catch (Throwable localThrowable)
516. {
517. }
518. throw newUndeclaredThrowableException(localThrowable);
519. }
520.
521. public final String toProxyConfigString()
522. throws
523. {
524. try
525. {
526. return (String)this.h.invoke(this, m14,null);
527. }
528. catch (RuntimeExceptionlocalRuntimeException)
529. {
530. throw localRuntimeException;
531. }
532. catch (Throwable localThrowable)
533. {
534. }
535. throw newUndeclaredThrowableException(localThrowable);
536. }
537.
538. static
539. {
540. try
541. {
542. m19 =Class.forName("org.springframework.aop.framework.Advised").getMethod("isPreFiltered",new Class[0]);
543. m15 = Class.forName("org.springframework.aop.framework.Advised").getMethod("isProxyTargetClass",new Class[0]);
544. m27 =Class.forName("org.springframework.core.DecoratingProxy").getMethod("getDecoratedClass",new Class[0]);
545. m6 = Class.forName("org.springframework.aop.framework.Advised").getMethod("isFrozen",new Class[0]);
546. m2 =Class.forName("java.lang.Object").getMethod("toString", newClass[0]);
547. m25 =Class.forName("org.springframework.aop.framework.Advised").getMethod("removeAdvice",new Class[] { Class.forName("org.aopalliance.aop.Advice") });
548. m24 =Class.forName("org.springframework.aop.framework.Advised").getMethod("removeAdvisor",new Class[] { Class.forName("org.springframework.aop.Advisor") });
549. m11 = Class.forName("org.springframework.aop.framework.Advised").getMethod("setExposeProxy",new Class[] { Boolean.TYPE });
550. m4 =Class.forName("org.springframework.aop.framework.Advised").getMethod("indexOf",new Class[] { Class.forName("org.springframework.aop.Advisor") });
551. m26 =Class.forName("org.springframework.aop.framework.Advised").getMethod("getTargetClass",new Class[0]);
552. m8 =Class.forName("org.springframework.aop.framework.Advised").getMethod("getTargetSource",new Class[0]);
553. m22 = Class.forName("org.springframework.aop.framework.Advised").getMethod("addAdvisor",new Class[] { Integer.TYPE,Class.forName("org.springframework.aop.Advisor") });
554. m20 =Class.forName("org.springframework.aop.framework.Advised").getMethod("isExposeProxy",new Class[0]);
555. m21 =Class.forName("org.springframework.aop.framework.Advised").getMethod("addAdvisor",new Class[] { Class.forName("org.springframework.aop.Advisor") });
556. m16 =Class.forName("org.springframework.aop.framework.Advised").getMethod("addAdvice",new Class[] { Integer.TYPE,Class.forName("org.aopalliance.aop.Advice") });
557. m9 =Class.forName("org.springframework.aop.framework.Advised").getMethod("getProxiedInterfaces",new Class[0]);
558. m23 =Class.forName("org.springframework.aop.framework.Advised").getMethod("removeAdvisor",new Class[] { Integer.TYPE });
559. m5 =Class.forName("org.springframework.aop.framework.Advised").getMethod("indexOf",new Class[] { Class.forName("org.aopalliance.aop.Advice") });
560. m12 = Class.forName("org.springframework.aop.framework.Advised").getMethod("setPreFiltered",new Class[] { Boolean.TYPE });
561. m13 =Class.forName("org.springframework.aop.framework.Advised").getMethod("replaceAdvisor",new Class[] { Class.forName("org.springframework.aop.Advisor"),Class.forName("org.springframework.aop.Advisor") });
562. m1 =Class.forName("java.lang.Object").getMethod("equals", newClass[] { Class.forName("java.lang.Object") });
563. m18 =Class.forName("org.springframework.aop.framework.Advised").getMethod("getAdvisors",new Class[0]);
564. m10 =Class.forName("org.springframework.aop.framework.Advised").getMethod("isInterfaceProxied",new Class[] { Class.forName("java.lang.Class") });
565. m17 =Class.forName("org.springframework.aop.framework.Advised").getMethod("addAdvice",new Class[] { Class.forName("org.aopalliance.aop.Advice") });
566. m3 =Class.forName("com.alipay.sofa.boot.examples.demo.rpc.bean.PersonService").getMethod("sayName",new Class[] { Class.forName("java.lang.String") });
567. m0 = Class.forName("java.lang.Object").getMethod("hashCode",new Class[0]);
568. m7 =Class.forName("org.springframework.aop.framework.Advised").getMethod("setTargetSource",new Class[] { Class.forName("org.springframework.aop.TargetSource")});
569. m14 = Class.forName("org.springframework.aop.framework.Advised").getMethod("toProxyConfigString",new Class[0]);
570. return;
571. }
572. catch (NoSuchMethodExceptionlocalNoSuchMethodException)
573. {
574. throw newNoSuchMethodError(localNoSuchMethodException.getMessage());
575. }
576. catch (ClassNotFoundExceptionlocalClassNotFoundException)
577. {
578. }
579. throw newNoClassDefFoundError(localClassNotFoundException.getMessage());
580. }
581. }
1.1.2 AOP代理之CGLIB动态代理
针对类(例如:com.alipay.sofa.boot.examples.demo.rpc.bean.PersonServiceImpl2),为其创建JVM服务的AOP代理对象的主要逻辑如下:
1. 创建handler,此处为ServiceProxy抽象类的子类JvmServiceInvoker的实例。该类继承了ServiceProxy,而ServiceProxy实现了org.aopalliance.intercept.MethodInterceptor接口,表示此处创建AOP代理的方法拦截器。该AOP代理拦截器拦截对proxyClass指定的接口(例如: PersonService)的方法调用。
2. 创建AOP代理工厂类org.springframework.aop.framework.ProxyFactory的实例factory;
3. 配置factory:如果javaClass为接口,则factory的interfaces列表中增加javaClass。否则,设置factory的targetClass为javaClass,proxyTarget为true。
4. 把指定的AOP advice实例handler增加到advice链尾部。
5. 调用factory的getProxy方法,为指定服务创建AOP代理对象。由于此处目标类是未实现任何接口的类,则使用CGLIB动态代理技术。Spring使用CGLIB来生成代理对象,具体的实现代码放在org.springframework.aop.framework.ObjenesisCglibAopProxy这个类中。
以上是使用CGLIB动态代理机制动态创建JVM服务的AOP代理对象的主要流程。
为了查看CGLIB动态生成的代理对象的源文件,必须先导出字节码文件,然后通过反编译工具(如:jad)生成源文件。对于CGLIB,导出字节码文件方式为在应用代码开始位置设置DebuggingClassWriter.DEBUG_LOCATION_PROPERTY值,此值为class文件的存储目录,如:E:/proxy/cglib:
1. @SpringBootApplication
2. @ImportResource({"classpath*:rpc-starter-example.xml" })
3. public class SofaBootRpcDemoApplication {
4.
5. publicstatic void main(String[] args) throws InterruptedException {
6.
7. System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"E:/proxy/cglib");
8.
9. ConfigurableApplicationContext ac =SpringApplication.run(SofaBootRpcDemoApplication.class, args);
10.
11.
12. }
13. }
以下为PersonServiceImpl2类的AOP代理对象的源文件: