一看讀懂反向代理
點(diǎn)擊上方藍(lán)色“程序猿DD”,選擇“設(shè)為星標(biāo)”
回復(fù)“資源”獲取獨(dú)家整理的學(xué)習(xí)資料!

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

2.3.1 被代理類實(shí)現(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 測(cè)試
@Test
public?void?staticProxy()?{
????HelloServiceStaticProxy helloServiceStaticProxy =?new?HelloServiceStaticProxy(new?HelloServiceImpl());
????helloServiceStaticProxy.hello();
}
你好,我是小王!
你吃了嘛?
好的,下次家里聊!
2.3.5 小結(jié)
2.4 動(dòng)態(tài)代理
2.4.1 動(dòng)態(tài)代理實(shí)現(xiàn)技術(shù)
基于jdk實(shí)現(xiàn) 基于Cglib實(shí)現(xiàn)
2.4.2 基于jdk實(shí)現(xiàn)
2.4.2.1 創(chuàng)建代理類,實(shí)現(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 測(cè)試
@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實(shí)現(xiàn)
2.4.3.1 創(chuàng)建代理類,實(shí)現(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 測(cè)試
@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動(dòng)態(tài)代理與cglib動(dòng)態(tài)代理的區(qū)別
jdk動(dòng)態(tài)代理不需要引入第三方包,需要實(shí)現(xiàn)InvocationHandler接口,要求被代理對(duì)象必須實(shí)現(xiàn)接口 cglib動(dòng)態(tài)代理需要引入第三方包,需要實(shí)現(xiàn)MethodInterceptor接口,被代理對(duì)象可以實(shí)現(xiàn)接口,也可以不實(shí)現(xiàn)接口
3. 總結(jié)
往期推薦

我的星球是否適合你?
點(diǎn)擊閱讀原文看看我們都聊過(guò)啥?
