日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

通俗易懂详解Java代理及代码实战

發(fā)布時(shí)間:2025/7/14 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 通俗易懂详解Java代理及代码实战 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、概述

  代理模式是Java常用的設(shè)計(jì)模式之一,實(shí)現(xiàn)代理模式要求代理類和委托類(被代理的類)具有相同的方法(提供相同的服務(wù)),代理類對(duì)象自身并不實(shí)現(xiàn)真正的核心邏輯,而是通過(guò)調(diào)用委托類對(duì)象的相關(guān)方法來(lái)處理核心邏輯,而代理類對(duì)象主要負(fù)責(zé)為委托類對(duì)象過(guò)濾消息、預(yù)處理消息、轉(zhuǎn)發(fā)消息給委托類、事后處理消息等等。通常代理類會(huì)與委托類存在關(guān)聯(lián)關(guān)系。

  按照代理的創(chuàng)建時(shí)期,代理可分為:靜態(tài)代理和動(dòng)態(tài)代理。靜態(tài)代理由開(kāi)發(fā)者手動(dòng)創(chuàng)建,在程序運(yùn)行前,已經(jīng)存在;而動(dòng)態(tài)代理不需要手動(dòng)創(chuàng)建,它是在程序運(yùn)行時(shí)動(dòng)態(tài)的創(chuàng)建代理類。

二、靜態(tài)代理

  我們直接用代碼來(lái)說(shuō)明什么叫靜態(tài)代理,場(chǎng)景是我要賣掉我的車子,但是由于我很忙,所以賣掉車子的過(guò)程中不想每天被電話騷擾,于是我就在附近找了一個(gè)二手車交易的中介,希望在他的幫助下很輕松的賣掉車子。 1.賣車子接口 public interface SaleCar {void sale(); }

2.hafiz真正賣車子實(shí)現(xiàn)類

public class HafizSaleCar implements SaleCar {@Overridepublic void sale() {System.out.println("hafiz sale his car...");} }

3.二手車交易中介類

public class CarTradeProxy implements SaleCar {private HafizSaleCar owner;public CarTradeProxy(HafizSaleCar owner) {this.owner = owner;}@Overridepublic void sale() {System.out.println("proxy add price...");owner.sale();} }

4.測(cè)試類

public class Client {public static void main(String[] args) {HafizSaleCar owner = new HafizSaleCar();CarTradeProxy proxy = new CarTradeProxy(owner);proxy.sale();} }

5.測(cè)試結(jié)果

從上面的代碼中,我們可以看出,其實(shí)代理類(CarTradeProxy)和委托類(HafizSaleCar)好像區(qū)別并不大,我們直接創(chuàng)建一個(gè)HafizSaleCar對(duì)象,然后調(diào)用它的sale()方法不就好了?細(xì)心的同學(xué)你會(huì)發(fā)現(xiàn),其實(shí)代理在真正調(diào)用委托類的方法之前做了中介加價(jià)的操作,這也就意味著我們使用代理模式實(shí)現(xiàn)在委托類的基礎(chǔ)上增加額外的邏輯操作。

  以上就是一個(gè)很簡(jiǎn)單的靜態(tài)代理的實(shí)現(xiàn)過(guò)程。但是這個(gè)時(shí)候我又有了一個(gè)新需求,我想用我手里的存款以及買車子賺的錢來(lái)給自己買一套新房子,那我又不想東奔西跑找房源,于是我又把買房這件事委托給了房產(chǎn)中介,下面我們就來(lái)實(shí)現(xiàn)這個(gè)邏輯。

1.再定義一個(gè)買房的接口

public interface BuyHouse {void buy(); }

2.重寫委托類,實(shí)現(xiàn)賣車和買房?jī)蓚€(gè)接口

public class HafizTrade implements SaleCar, BuyHouse {@Overridepublic void buy() {System.out.println("hafiz buy house...");}@Overridepublic void sale() {System.out.println("hafiz sale car...");} }

可以看到,我現(xiàn)在既要賣掉我的車子,又要購(gòu)買新的房子。

3.再創(chuàng)建一個(gè)買房子的中介代理類

public class HouseTradeProxy implements BuyHouse {private HafizTrade customer;public HouseTradeProxy(HafizTrade customer) {this.customer = customer;}@Overridepublic void buy() {System.out.println("proxy add price...");customer.buy();} }

4.賣車子的代理類修改如下

public class CarTradeProxy implements SaleCar {private HafizTrade owner;public CarTradeProxy(HafizTrade owner) {this.owner = owner;}@Overridepublic void sale() {System.out.println("proxy add price...");owner.sale();} }

5.新的測(cè)試類

public class Client {public static void main(String[] args) {HafizTrade trader = new HafizTrade();CarTradeProxy carTradeProxy = new CarTradeProxy(trader);carTradeProxy.sale();System.out.println("-----------------------------------------------");HouseTradeProxy houseTradeProxy = new HouseTradeProxy(trader);houseTradeProxy.buy();System.out.println("-----------------------------------------------");} }

6.測(cè)試結(jié)果

這樣通過(guò)靜態(tài)代理的方式,我們的確也可以很完美的解決我們的問(wèn)題,但當(dāng)我們有越來(lái)越多的委托類需要代理,而且代理做的工作又一樣,那是不是會(huì)多出來(lái)很多的代理類,我們開(kāi)發(fā)者會(huì)瘋掉的,這時(shí)候我們就想:如果我們可以只做一次,就能代理一類委托類該多好啊?那么這個(gè)時(shí)候,動(dòng)態(tài)代理就應(yīng)運(yùn)而生了,它可以使得我們只定義一次就能為一類委托類做代理。

三、動(dòng)態(tài)代理

  靜態(tài)代理要求我們?cè)诔绦虬l(fā)布上線運(yùn)行之前,就要開(kāi)發(fā)好對(duì)應(yīng)委托類的代理類,而動(dòng)態(tài)代理是我們?cè)诔绦虬l(fā)布之前,并沒(méi)有創(chuàng)建好對(duì)應(yīng)的代理類,而是在運(yùn)行的時(shí)候動(dòng)態(tài)的創(chuàng)建代理類。
  動(dòng)態(tài)代理實(shí)現(xiàn)方式有兩種:jdk自帶動(dòng)態(tài)代理實(shí)現(xiàn)以及cglib實(shí)現(xiàn)。jdk代理只適合代理實(shí)現(xiàn)接口的目標(biāo)對(duì)象,cglib可以代理沒(méi)有實(shí)現(xiàn)接口的目標(biāo)對(duì)象。

四、基于JDK實(shí)現(xiàn)動(dòng)態(tài)代理

1.實(shí)現(xiàn)步驟

  1).通過(guò)實(shí)現(xiàn) InvocationHandler 接口創(chuàng)建自己的調(diào)用處理器

  2).通過(guò)為 Proxy 類指定 ClassLoader 對(duì)象和一組 interface 來(lái)創(chuàng)建動(dòng)態(tài)代理類

  3).通過(guò)反射機(jī)制獲得動(dòng)態(tài)代理類的構(gòu)造函數(shù)(jdk自帶,不需手動(dòng)處理)

  4).通過(guò)構(gòu)造函數(shù)創(chuàng)建動(dòng)態(tài)代理類實(shí)例,構(gòu)造時(shí)調(diào)用處理器對(duì)象作為參數(shù)被傳入(jdk自帶,不需手動(dòng)處理)

2.創(chuàng)建代理處理器

public class ProxyHandler implements InvocationHandler {private Object target;public ProxyHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("proxy add price...");Object result = method.invoke(target, args);return result;} }

3.測(cè)試類

public class Client {public static void main(String[] args) {HafizTrade trader = new HafizTrade();ProxyHandler handler = new ProxyHandler(trader);Class<? extends HafizTrade> clazz = trader.getClass();ClassLoader classLoader = clazz.getClassLoader();Class<?>[] interfaces = clazz.getInterfaces();SaleCar carProxy = (SaleCar)Proxy.newProxyInstance(classLoader, interfaces, handler);carProxy.sale();System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++");BuyHouse houseProxy = (BuyHouse)Proxy.newProxyInstance(classLoader, interfaces, handler);houseProxy.buy();System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++");} }

4.測(cè)試結(jié)果

5.原理

  生成一個(gè)代理類,這個(gè)代理類繼承Proxy類并且實(shí)現(xiàn)了我們定義的接口,代理對(duì)象調(diào)用方法的時(shí)候,調(diào)用這個(gè)代理對(duì)象的一個(gè)成員InvocationHandler(上面我們傳入了一個(gè)InvocationHandler實(shí)現(xiàn)對(duì)象)的方法,也就是我們包裝了委托類后的方法。

五、基于cglib實(shí)現(xiàn)動(dòng)態(tài)代理

1.實(shí)現(xiàn)步驟

  1).通過(guò)實(shí)現(xiàn)CGLib包提供的MethodInterceptor接口,重寫intercept方法,創(chuàng)建自己的方法攔截器

  2).通過(guò)CGLib中的Enhancer的creat方法創(chuàng)建動(dòng)態(tài)代理對(duì)象

2.添加cglib的maven依賴

<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>2.2.2</version> </dependency>

3.自定義ProxyInterceptor

public class ProxyInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("Trade proxy add price...");Object result = methodProxy.invokeSuper(o, objects);return result;} }

4.測(cè)試client

public class Client {public static void main(String[] args) {ProxyInterceptor proxy = new ProxyInterceptor();HafizTrade tradeProxy = (HafizTrade)Enhancer.create(HafizTrade.class, proxy);tradeProxy.sale();System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++");tradeProxy.buy();} }

5.測(cè)試結(jié)果

6.原理

  首先通過(guò)asm字節(jié)碼生成框架生成代理類Class的二進(jìn)制字節(jié)碼,然后通過(guò)Class.forName加載二進(jìn)制字節(jié)碼,生成Class對(duì)象,最后通過(guò)反射機(jī)制獲取實(shí)例構(gòu)造,并初始化代理類對(duì)象。

六、總結(jié)

  動(dòng)態(tài)代理可以使得我們一次可以解決一批需要?jiǎng)?chuàng)建代理的問(wèn)題,使得代碼更加靈活,提高了程序的擴(kuò)展性。動(dòng)態(tài)代理在主流java框架中也非常常用,比如最著名的spring,它在AOP的功能就是使用動(dòng)態(tài)代理實(shí)現(xiàn),還有Dubbo等這樣的RPC服務(wù)框架,在客戶端都是通過(guò)代理完成服務(wù)的真正調(diào)用。了解和學(xué)會(huì)代理以及實(shí)現(xiàn)方式能幫助我們更好地理解主流框架。

  關(guān)于動(dòng)態(tài)代理的實(shí)現(xiàn)細(xì)節(jié),可以參考:http://www.360doc.com/content/14/0801/14/1073512_398598312.shtml#

《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的通俗易懂详解Java代理及代码实战的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。