一看就懂RPC之反向代理
點擊上方“JAVA”,星標公眾號

作者:黑白搬磚工
juejin.im/post/6844904116888535054
1.前言
系統(tǒng)開發(fā)已經由單體服務轉向為一個一個的微小服務,微小服務的好處就是每個服務只需要關心自己內部的業(yè)務,當需要相關業(yè)務數(shù)據(jù)的時候,就會面臨服務調用的問題,服務調用其實也好解決,可以使用java自帶的HttpURLConnection進行遠程服務的調用,也可以使用HttpClient或者是OkHttp這樣的第三方客戶端進行遠程服務調用,同樣也可以使用高性能遠程調用框架Dubbo。
目前比較流行的微服務技術棧,可以使用基于Netty實現(xiàn)的Dubbo,或者使用基于Http實現(xiàn)的SpringCloud,不管哪種技術,為了實現(xiàn)遠程過程調用的便利性,使開發(fā)者只需要關注業(yè)務本身,而不需要關注調用細節(jié),都采取了反向代理技術。反向代理技術在實現(xiàn)服務間透明調用起到了非常重要作用,既然重要,那么就有必要和大家一起來溫習一下反向代理技術。
2.反向代理
2.1 代理的作用
代理的作用就是增強目標方法的能力,比如最常見的事務、Aop都是基于代理來實現(xiàn)的。當需要增強目標方法的能力,并且這些能力都是相同的,那么就可以采取代理的方式進行實現(xiàn)。
2.2 代理的分類
靜態(tài)代理:靜態(tài)代理需要為每個被代理的類創(chuàng)建一個代理類,當被代理的類過多的時候,就會導致代理類的增多,不便于維護。動態(tài)代理:動態(tài)代理不需要為每個被代理的類創(chuàng)建一個代理類,只需要一個全局的代理類,在需要的時候動態(tài)生成,便于維護。
2.3 靜態(tài)代理

如圖可以看到被代理類實現(xiàn)的接口和被代理類其實就是我們開發(fā)的業(yè)務接口和業(yè)務接口實現(xiàn)類,在需要代理的情況下,代理類也要實現(xiàn)被代理類實現(xiàn)的接口,接下來我們來看一下代碼的實現(xiàn)。
2.3.1 被代理類實現(xiàn)的接口
public?interface?HelloService?{
????void?hello();
}
2.3.2 被代理類
public?class?HelloServiceImpl?implements?HelloService?{
????public?void?hello()?{
????????System.out.println("你吃了嘛?");
????}
}
2.3.3 代理類
public?class?HelloServiceStaticProxy?implements?HelloService?{
????private?HelloService?helloService;
????public?HelloServiceStaticProxy(HelloService?helloService)?{
????????this.helloService?=?helloService;
????}
????public?void?hello()?{
????????System.out.println("你好,我是小王!");
????????this.helloService.hello();
????????System.out.println("好的,下次家里聊!");
????}
}
2.3.4 測試
@Test
public?void?staticProxy()?{
????HelloServiceStaticProxy?helloServiceStaticProxy?=?new?HelloServiceStaticProxy(new?HelloServiceImpl());
????helloServiceStaticProxy.hello();
}
你好,我是小王!
你吃了嘛?
好的,下次家里聊!
2.3.5 小結
靜態(tài)代理要求代理類和被代理類實現(xiàn)同一個接口,代理對象需要持有被代理的目標對象,在代理對象實現(xiàn)接口方法前后添加增強邏輯并調用目標對象方法。
搜索Java知音,回復“后端面試”,送你一份面試寶典.pdf
2.4 動態(tài)代理
2.4.1 動態(tài)代理實現(xiàn)技術
基于jdk實現(xiàn)基于Cglib實現(xiàn)
2.4.2 基于jdk實現(xiàn)
2.4.2.1 創(chuàng)建代理類,實現(xiàn)InvocationHandler接口
public?class?JdkDynamicProxy?implements?InvocationHandler?{
????private?Object?target;
????public?JdkDynamicProxy(Object?target)?{
????????this.target?=?target;
????}
????public?Object?getTarget()?{
????????return?target;
????}
????public?void?setTarget(Object?target)?{
????????this.target?=?target;
????}
????@Override
????public?Object?invoke(Object?proxy,?Method?method,?Object[]?args)?throws?Throwable?{
????????System.out.println("你好,我是小王!");
????????Object?result?=?method.invoke(target,?args);
????????System.out.println("好的,下次家里聊!");
????????return?result;
????}
}
2.4.2.2 創(chuàng)建代理工廠類
public?class?JdkDynamicProxyFactory?{
????private?JdkDynamicProxy?jdkDynamicProxy;
????public?JdkDynamicProxyFactory(JdkDynamicProxy?helloServiceJdkDynamicProxy)?{
????????this.jdkDynamicProxy?=?helloServiceJdkDynamicProxy;
????}
????public?Object?getProxy()?{
????????Object?target?=?jdkDynamicProxy.getTarget();
????????return?Proxy.newProxyInstance(jdkDynamicProxy.getClass().getClassLoader(),?target.getClass().getInterfaces(),?jdkDynamicProxy);
????}
}
2.4.2.3 測試
@Test
public?void?test()?{
????JdkDynamicProxy?jdkDynamicProxy?=?new?JdkDynamicProxy(new?HelloServiceImpl());
????JdkDynamicProxyFactory?proxyFactory?=?new?JdkDynamicProxyFactory(jdkDynamicProxy);
????HelloService?proxy?=?(HelloService)?proxyFactory.getProxy();
????proxy.hello();
}
你好,我是小王!
你吃了嘛?
好的,下次家里聊!
2.4.3 基于cglib實現(xiàn)
2.4.3.1 創(chuàng)建代理類,實現(xiàn)MethodInterceptor接口
public?class?CglibDynamicProxy?implements?MethodInterceptor?{
????private?Object?target;
????public?CglibDynamicProxy(Object?target)?{
????????this.target?=?target;
????}
????public?Object?getTarget()?{
????????return?target;
????}
????public?void?setTarget(Object?target)?{
????????this.target?=?target;
????}
????@Override
????public?Object?intercept(Object?o,?Method?method,?Object[]?args,?MethodProxy?methodProxy)?throws?Throwable?{
????????System.out.println("你好,我是小王!");
????????Object?result?=?method.invoke(target,?args);
????????System.out.println("好的,下次家里聊!");
????????return?result;
????}
}
2.4.3.2 創(chuàng)建代理工廠類
public?class?CglibDynamicProxyFactory?{
????private?CglibDynamicProxy?cglibDynamicProxy;
????public?CglibDynamicProxyFactory(CglibDynamicProxy?cglibDynamicProxy)?{
????????this.cglibDynamicProxy?=?cglibDynamicProxy;
????}
????public?Object?getProxy()?{
????????Enhancer?enhancer?=?new?Enhancer();
????????enhancer.setInterfaces(cglibDynamicProxy.getTarget().getClass().getInterfaces());
????????enhancer.setCallback(cglibDynamicProxy);
????????return?enhancer.create();
????}
}
2.4.3.3 測試
@Test
public?void?test()?{
????CglibDynamicProxy?cglibDynamicProxy?=?new?CglibDynamicProxy(new?HelloServiceImpl());
????CglibDynamicProxyFactory?proxyFactory?=?new?CglibDynamicProxyFactory(cglibDynamicProxy);
????HelloService?proxy?=?(HelloService)?proxyFactory.getProxy();
????proxy.hello();
}
你好,我是小王!
你吃了嘛?
好的,下次家里聊!
2.4.4 jdk動態(tài)代理與cglib動態(tài)代理的區(qū)別
jdk動態(tài)代理不需要引入第三方包,需要實現(xiàn)InvocationHandler接口,要求被代理對象必須實現(xiàn)接口
cglib動態(tài)代理需要引入第三方包,需要實現(xiàn)MethodInterceptor接口,被代理對象可以實現(xiàn)接口,也可以不實現(xiàn)接口
3. 總結
今天和大家一起溫習了一下代理的相關技術,代理分為:靜態(tài)代理和動態(tài)代理,動態(tài)代理的實現(xiàn)技術有:基于jdk來實現(xiàn)和基于cglib來實現(xiàn),cglib可以針對沒有實現(xiàn)接口的目標對象進行代理。代理技術是后續(xù)篇章的講解的基石,只有掌握代理技術,才能更好的去學習、實現(xiàn)遠程過程調用,希望你能牢牢掌握該門技術,可以讓自己在后續(xù)的篇章中無任何絆腳石。
更多精彩?
在公眾號【程序員編程】對話框輸入以下關鍵詞 查看更多優(yōu)質內容! 大數(shù)據(jù)?|?Java?|?1024?|?電子書?|?速查表? Python進階?|?面試?|?手冊?|?成神?|?思想?|?小程序 命令行?|?人工智能?|?軟件測試?|?Web前端?|?Python 獲取更多學習資料
視頻 |?面試 |?技術 | 電子書?
