Java源文件:即咱們在IDE裏面寫的.java文件java
Java字節碼:即編譯器編譯以後的.class文件(javac命令).備註:Java代碼爲什麼可以跨平臺,和Java字節碼技術是分不開的,這個字節碼在windows,在linux下都是能夠運行的linux
class對象:工程啓動的時候classLoader類加載器會掃描這些字節碼並加載到classLoader上面生成class對象,有了類對象,即可以new實例了。(class對象保存在方法區元空間JDK1.8)算法
卸載:垃圾回收,關於回收機制,算法有興趣能夠去了解。class對象何時被回收?答:可達性分析,當發現某個類不被引用,類會被回收windows
既然是直接生成的Java字節碼,是怎麼生成的?從源碼開始分析,從Proxy.newProxyInstance方法開始看。數組
Class<?> cl = getProxyClass0(loader, intfs);這行代碼生成了.class字節碼而且生成了class對象,而後拿這個類對象獲取構造函數,再newInstance,生成實例對象,是經過反射的機制。重點仍是怎麼生成.class字節碼。tomcat
接下來apply()方法往下看網絡
生成了字節碼數組,從而生成了Java字節碼,defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length)則是加載字節碼文件,此方法爲native方法,C語言方法,操做系統類庫(C/C++/彙編)。app
字節碼文件的結構是如何的呢?咱們把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(); }
在剛剛的動態代理測試類增長几行代碼:工具
public static void main(String[] args) throws IOException { // 代購公司C,負責代購全部產品 DynamicProxyCompanyC proxy = new DynamicProxyCompanyC(); // 日本有家A公司生產男性用品 ManToolFactory dogToolFactory = new AManFactory(); // 代購A公司的產品 proxy.setFactory(dogToolFactory); // 建立A公司的代理對象 ManToolFactory proxyObject = (ManToolFactory) proxy.getProxyInstance(); // 代理對象完成代購男性用品 proxyObject.saleManTool("D"); System.out.println("--------------"); // 日本有家B公司生產女性用品 WomanToolFactory womanToolFactory = new BWomanFactory(); // 代購B公司的產品 proxy.setFactory(womanToolFactory); // 建立B公司的代理對象 WomanToolFactory proxyObject1 = (WomanToolFactory) proxy.getProxyInstance(); // 代理對象完成代購女性用品 proxyObject1.saleWomanTool(1.8); //生成代理類的.class文件 DynamicProxyCompanyC.generateClass(proxyObject1.getClass().getSimpleName(), womanToolFactory.getClass().getInterfaces(), womanToolFactory.getClass()); }
根據打印出來的class文件路徑打開並在反編譯工具上打開
動態代理生成的類就是這個了,調用業務方法saleWomanTool實際上變成了這個h.invoke,而這個h是全部Proxy類裏面含有的 protected InvocationHandler h;(源碼可見),在用Proxy建立代理實例的時候已經傳入過了。
因此調用方法saleWomanTool就有了前置加強和後置加強。到這裏已經解開了動態代理的原理