摘要:對(duì)象什么時(shí)候被回收答可達(dá)性分析,當(dāng)發(fā)現(xiàn)某個(gè)類不被引用,類會(huì)被回收類的生命周期與動(dòng)態(tài)代理關(guān)系動(dòng)態(tài)代理是沒有源文件,直接生成字節(jié)碼的,加載到上面的。
上節(jié)講到動(dòng)態(tài)代理生成的類為$Proxy0,但是在我們項(xiàng)目里面卻不存在,實(shí)際我們是用了這個(gè)實(shí)現(xiàn)類調(diào)用了方法,想要知道這個(gè)問題,首先要理解類的完整生命周期.
類的完整生命周期Java源文件:即我們?cè)贗DE里面寫的.java文件
Java字節(jié)碼:即編譯器編譯之后的.class文件(javac命令).備注:Java代碼為何能夠跨平臺(tái),和Java字節(jié)碼技術(shù)是分不開的,這個(gè)字節(jié)碼在windows,在linux下都是可以運(yùn)行的
class對(duì)象:工程啟動(dòng)的時(shí)候classLoader類加載器會(huì)掃描這些字節(jié)碼并加載到classLoader上面生成class對(duì)象,有了類對(duì)象,便可以new實(shí)例了。(class對(duì)象保存在方法區(qū)元空間JDK1.8)
卸載:垃圾回收,關(guān)于回收機(jī)制,算法有興趣可以去了解。class對(duì)象什么時(shí)候被回收?答:可達(dá)性分析,當(dāng)發(fā)現(xiàn)某個(gè)類不被引用,類會(huì)被回收
類的生命周期與動(dòng)態(tài)代理關(guān)系動(dòng)態(tài)代理是沒有Java源文件,直接生成Java字節(jié)碼的,加載到JVM上面的。字節(jié)碼來源于內(nèi)存,比如tomcat的熱加載就是從網(wǎng)絡(luò)傳輸過來的。
既然是直接生成的Java字節(jié)碼,是怎么生成的?從源碼開始分析,從Proxy.newProxyInstance方法開始看。
Class> cl = getProxyClass0(loader, intfs);這行代碼生成了.class字節(jié)碼并且生成了class對(duì)象,然后拿這個(gè)類對(duì)象獲取構(gòu)造函數(shù),再newInstance,生成實(shí)例對(duì)象,是通過反射的機(jī)制。重點(diǎn)還是怎么生成.class字節(jié)碼。
接下來apply()方法往下看
生成了字節(jié)碼數(shù)組,從而生成了Java字節(jié)碼,defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length)則是加載字節(jié)碼文件,此方法為native方法,C語言方法,操作系統(tǒng)類庫(kù)(C/C++/匯編)。
字節(jié)碼文件的結(jié)構(gòu)是如何的呢?我們把class文件生成出來并在反編譯工具打開,這里就用到了源碼里面的方法了。生成.class文件的代碼如下:
public static void generateClass(String proxyName, Class[] paramArrayOfClass, Class clazz) throws IOException { byte[] classFile=ProxyGenerator.generateProxyClass( proxyName, paramArrayOfClass); String path=clazz.getResource(".").getPath(); System.out.println(path); FileOutputStream outputStream =null; outputStream = new FileOutputStream(path + proxyName + "p.class"); outputStream.write(classFile); outputStream.flush(); outputStream.close(); }
在剛剛的動(dòng)態(tài)代理測(cè)試類增加幾行代碼:
public static void main(String[] args) throws IOException { // 代購(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); //生成代理類的.class文件 DynamicProxyCompanyC.generateClass(proxyObject1.getClass().getSimpleName(), womanToolFactory.getClass().getInterfaces(), womanToolFactory.getClass()); }
根據(jù)打印出來的class文件路徑打開并在反編譯工具上打開
動(dòng)態(tài)代理生成的類就是這個(gè)了,調(diào)用業(yè)務(wù)方法saleWomanTool實(shí)際上變成了這個(gè)h.invoke,而這個(gè)h是所有Proxy類里面含有的 protected InvocationHandler h;(源碼可見),在用Proxy創(chuàng)建代理實(shí)例的時(shí)候已經(jīng)傳入過了。
所以調(diào)用方法saleWomanTool就有了前置增強(qiáng)和后置增強(qiáng)。到這里已經(jīng)解開了動(dòng)態(tài)代理的原理
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/73693.html
摘要:值得一提的是由于采用動(dòng)態(tài)創(chuàng)建子類的方式生成代理對(duì)象,所以不能對(duì)目標(biāo)類中的方法進(jìn)行代理。動(dòng)態(tài)代理中生成的代理類是子類,調(diào)試的時(shí)候可以看到,打開源碼可看到實(shí)現(xiàn)了和也就實(shí)現(xiàn)方法。 前面講到了動(dòng)態(tà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è)限制...
摘要:緊接著上節(jié),為了解決靜態(tài)代理的問題,出現(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è)注釋是說提供個(gè)一個(gè)靜態(tài)方法來創(chuàng)建代理類和代理實(shí)例,它也是所有由此方法創(chuàng)建的代理類的父類。 緊接著上節(jié),為了解決靜態(tài)代理的問題,出現(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)...
摘要:是一種特殊的增強(qiáng)切面切面由切點(diǎn)和增強(qiáng)通知組成,它既包括了橫切邏輯的定義也包括了連接點(diǎn)的定義。實(shí)際上,一個(gè)的實(shí)現(xiàn)被拆分到多個(gè)類中在中聲明切面我們知道注解很方便,但是,要想使用注解的方式使用就必須要有源碼因?yàn)槲覀円? 前言 只有光頭才能變強(qiáng) 上一篇已經(jīng)講解了Spring IOC知識(shí)點(diǎn)一網(wǎng)打盡!,這篇主要是講解Spring的AOP模塊~ 之前我已經(jīng)寫過一篇關(guān)于AOP的文章了,那篇把比較重要的知...
摘要:在上文中,我實(shí)現(xiàn)了一個(gè)很簡(jiǎn)單的和容器。比如,我們所熟悉的就是在這里將切面邏輯織入相關(guān)中的。初始化的工作算是結(jié)束了,此時(shí)處于就緒狀態(tài),等待外部程序的調(diào)用。其中動(dòng)態(tài)代理只能代理實(shí)現(xiàn)了接口的對(duì)象,而動(dòng)態(tài)代理則無此限制。 1. 背景 本文承接上文,來繼續(xù)說說 IOC 和 AOP 的仿寫。在上文中,我實(shí)現(xiàn)了一個(gè)很簡(jiǎn)單的 IOC 和 AOP 容器。上文實(shí)現(xiàn)的 IOC 和 AOP 功能很單一,且 I...
摘要:,,面向切面編程。,切點(diǎn),切面匹配連接點(diǎn)的點(diǎn),一般與切點(diǎn)表達(dá)式相關(guān),就是切面如何切點(diǎn)。例子中,注解就是切點(diǎn)表達(dá)式,匹配對(duì)應(yīng)的連接點(diǎn),通知,指在切面的某個(gè)特定的連接點(diǎn)上執(zhí)行的動(dòng)作。,織入,將作用在的過程。因?yàn)樵创a都是英文寫的。 之前《零基礎(chǔ)帶你看Spring源碼——IOC控制反轉(zhuǎn)》詳細(xì)講了Spring容器的初始化和加載的原理,后面《你真的完全了解Java動(dòng)態(tài)代理嗎?看這篇就夠了》介紹了下...
閱讀 3571·2021-11-12 10:36
閱讀 2973·2021-09-22 15:35
閱讀 2895·2021-09-04 16:41
閱讀 1251·2019-08-30 15:55
閱讀 3654·2019-08-29 18:43
閱讀 2141·2019-08-23 18:24
閱讀 1484·2019-08-23 18:10
閱讀 1981·2019-08-23 11:31