摘要:緊接著上節(jié),為了解決靜態(tài)代理的問(wèn)題,出現(xiàn)了動(dòng)態(tài)代理,假設(shè)動(dòng)態(tài)代理是一個(gè)代購(gòu)公司,私有變量為動(dòng)態(tài)生成的具體的真實(shí)對(duì)象,可代購(gòu)對(duì)應(yīng)的產(chǎn)品。這個(gè)注釋是說(shuō)提供個(gè)一個(gè)靜態(tài)方法來(lái)創(chuàng)建代理類和代理實(shí)例,它也是所有由此方法創(chuàng)建的代理類的父類。
緊接著上節(jié),為了解決靜態(tài)代理的問(wèn)題,出現(xiàn)了動(dòng)態(tài)代理, 假設(shè)動(dòng)態(tài)代理是一個(gè)代購(gòu)公司,私有變量Object factory為動(dòng)態(tài)生成的具體的真實(shí)對(duì)象,可代購(gòu)對(duì)應(yīng)的產(chǎn)品 。代碼:
/** * 動(dòng)態(tài)代理 */ public class DynamicProxyCompanyC implements InvocationHandler { // 被代理的對(duì)象,即真實(shí)對(duì)象 private Object factory; public Object getFactory() { return factory; } public void setFactory(Object factory) { this.factory = factory; } // 通過(guò)proxy獲取動(dòng)態(tài)代理的對(duì)象 public Object getProxyInstance() { //第三個(gè)參數(shù)是InvocationHandler,傳入自身說(shuō)明此proxy對(duì)象是和自身的invoke方法合作的,代理對(duì)象方法調(diào)用會(huì)經(jīng)過(guò)下面invoke的增強(qiáng) return Proxy.newProxyInstance(factory.getClass().getClassLoader(), factory.getClass().getInterfaces(), this); } @Override /**通過(guò)動(dòng)態(tài)代理對(duì)象對(duì)方法進(jìn)行增強(qiáng) * @param proxy 代理對(duì)象 * @param method 要增強(qiáng)的方法(攔截的方法) * @param args 方法參數(shù) */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { dosomeThingBefore(); Object ret = method.invoke(factory, args);// 通過(guò)反射機(jī)制調(diào)用方法 dosomeThingAfter(); return ret; } public void dosomeThingBefore() { System.out.println("售前服務(wù),負(fù)責(zé)產(chǎn)品調(diào)研,興趣愛(ài)好"); } public void dosomeThingAfter() { System.out.println("售后服務(wù),包裝丶送貨上門一條龍服務(wù)"); } }
測(cè)試類:
public class Proxytest { public static void main(String[] args) { // 代購(gòu)公司C,負(fù)責(zé)代購(gòu)所有產(chǎn)品 DynamicProxyCompanyC proxy = new DynamicProxyCompanyC(); // 日本有家A公司生產(chǎn)男性用品 ManToolFactory dogToolFactory = new AManFactory(); // 代購(gòu)A公司的產(chǎn)品 proxy.setFactory(dogToolFactory); // 創(chuàng)建A公司的代理對(duì)象 ManToolFactory proxyObject = (ManToolFactory) proxy.getProxyInstance(); // 代理對(duì)象完成代購(gòu)男性用品 proxyObject.saleManTool("D"); System.out.println("--------------"); // 日本有家B公司生產(chǎn)女性用品 WomanToolFactory womanToolFactory = new BWomanFactory(); // 代購(gòu)B公司的產(chǎn)品 proxy.setFactory(womanToolFactory); // 創(chuàng)建B公司的代理對(duì)象 WomanToolFactory proxyObject1 = (WomanToolFactory) proxy.getProxyInstance(); // 代理對(duì)象完成代購(gòu)女性用品 proxyObject1.saleWomanTool(1.8); } } // 售前服務(wù),負(fù)責(zé)產(chǎn)品調(diào)研,興趣愛(ài)好 // A工廠出售男性用品,D罩杯 // 售后服務(wù),包裝丶送貨上門一條龍服務(wù) // -------------- // 售前服務(wù),負(fù)責(zé)產(chǎn)品調(diào)研,興趣愛(ài)好 // B工廠生產(chǎn)女性用品,長(zhǎng)度1.8米 // 售后服務(wù),包裝丶送貨上門一條龍服務(wù)
動(dòng)態(tài)代理解決了上節(jié)說(shuō)的開(kāi)閉原則,那么接下來(lái)我們要解密動(dòng)態(tài)代理的原理,重點(diǎn)類DynamicProxyCompanyC
1.實(shí)現(xiàn)了InvocationHandler接口;
2.通過(guò)proxy獲取動(dòng)態(tài)代理的對(duì)象。
根據(jù)我們此例子里面來(lái)說(shuō),動(dòng)態(tài)代理就類似一個(gè)代購(gòu)公司,可代購(gòu)所有產(chǎn)品,需要購(gòu)買哪個(gè)產(chǎn)品的時(shí)候就實(shí)例化一個(gè)真實(shí)對(duì)象(如測(cè)試類需要男性用品則將接口引用指向真實(shí)對(duì)象AManFactory),根據(jù)真實(shí)對(duì)象創(chuàng)建代理對(duì)象來(lái)執(zhí)行具體的方法,圖解如下:
Proxy:接下來(lái)我們先初步看一下JDK里面的Proxy這個(gè)源碼。
這個(gè)注釋是說(shuō)Proxy提供個(gè)一個(gè)靜態(tài)方法來(lái)創(chuàng)建代理類和代理實(shí)例,它也是所有由此方法創(chuàng)建的代理類的父類。
靜態(tài)方法創(chuàng)建代理實(shí)例即方法newProxyInstance(ClassLoader loader,Class>[]interfaces,InvocationHandler h);
InvocationHandler 是一個(gè)接口,定義了invoke(Object proxy, Method method, Object[] args)方法
總的來(lái)說(shuō)Proxy專門負(fù)責(zé)new一個(gè)實(shí)例(真實(shí)對(duì)象),而具體方法做什么,業(yè)務(wù)怎樣增強(qiáng)就由InvocationHandler(抽象對(duì)象)的invoke方法(抽象對(duì)象即接口定義的方法)來(lái)決定。
接下來(lái)我們要搞清楚動(dòng)態(tài)代理的底層原理,首先我們調(diào)試一下test類,會(huì)發(fā)現(xiàn) ManToolFactory proxyObject = (ManToolFactory) proxy.getProxyInstance()中創(chuàng)建的proxyObject 對(duì)象類名是$Proxy0,是ManToolFactory接口的實(shí)現(xiàn)類。但是我們項(xiàng)目工程里面卻沒(méi)有$Proxy0這個(gè)類,那它究竟是怎么出現(xiàn)的,下節(jié)講解。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/73671.html
摘要:值得一提的是由于采用動(dòng)態(tài)創(chuàng)建子類的方式生成代理對(duì)象,所以不能對(duì)目標(biāo)類中的方法進(jìn)行代理。動(dòng)態(tài)代理中生成的代理類是子類,調(diào)試的時(shí)候可以看到,打開(kāi)源碼可看到實(shí)現(xiàn)了和也就實(shí)現(xiàn)方法。 前面講到了動(dòng)態(tài)代理的底層原理,接下來(lái)我們來(lái)看一下aop的動(dòng)態(tài)代理.Spring AOP使用了兩種代理機(jī)制:一種是基于JDK的動(dòng)態(tài)代理,一種是基于CGLib的動(dòng)態(tài)代理. ①JDK動(dòng)態(tài)代理:使用JDK創(chuàng)建代理有一個(gè)限制...
摘要:對(duì)象什么時(shí)候被回收答可達(dá)性分析,當(dāng)發(fā)現(xiàn)某個(gè)類不被引用,類會(huì)被回收類的生命周期與動(dòng)態(tài)代理關(guān)系動(dòng)態(tài)代理是沒(méi)有源文件,直接生成字節(jié)碼的,加載到上面的。 上節(jié)講到動(dòng)態(tài)代理生成的類為$Proxy0,但是在我們項(xiàng)目里面卻不存在,實(shí)際我們是用了這個(gè)實(shí)現(xiàn)類調(diào)用了方法,想要知道這個(gè)問(wèn)題,首先要理解類的完整生命周期. 類的完整生命周期 showImg(https://segmentfault.com/im...
摘要:總結(jié)動(dòng)態(tài)代理的相關(guān)原理已經(jīng)講解完畢,接下來(lái)讓我們回答以下幾個(gè)思考題。 【干貨點(diǎn)】 此處是【好好面試】系列文的第12篇文章。文章目標(biāo)主要是通過(guò)原理剖析的方式解答Aop動(dòng)態(tài)代理的面試熱點(diǎn)問(wèn)題,通過(guò)一步步提出問(wèn)題和了解原理的方式,我們可以記得更深更牢,進(jìn)而解決被面試官卡住喉嚨的情況。問(wèn)題如下 SpringBoot默認(rèn)代理類型是什么 為什么不用靜態(tài)代理 JDK動(dòng)態(tài)代理原理 CGLIB動(dòng)態(tài)代理...
摘要:修飾者模式設(shè)計(jì)模式中的修飾者模式能動(dòng)態(tài)地給目標(biāo)對(duì)象增加額外的職責(zé)。修飾者模式調(diào)用的時(shí)序圖如下圖所示。的實(shí)現(xiàn)原理和修飾者模式類似。 ?在上邊一篇文章中我們介紹了Spring AOP的基本概念,今天我們就來(lái)學(xué)習(xí)一下與AOP實(shí)現(xiàn)相關(guān)的修飾者模式和Java Proxy相關(guān)的原理,為之后源碼分析打下基礎(chǔ)。 修飾者模式 ?Java設(shè)計(jì)模式中的修飾者模式能動(dòng)態(tài)地給目標(biāo)對(duì)象增加額外的職責(zé)(Respon...
閱讀 1203·2021-11-17 09:33
閱讀 3599·2021-09-28 09:42
閱讀 3326·2021-09-13 10:35
閱讀 2478·2021-09-06 15:00
閱讀 2438·2021-08-27 13:12
閱讀 3609·2021-07-26 23:38
閱讀 1826·2019-08-30 15:55
閱讀 539·2019-08-30 15:53