緊接着上節,爲了解決靜態代理的問題,出現了動態代理, 假設動態代理是一個代購公司,私有變量Object factory爲動態生成的具體的真實對象,可代購對應的產品 。代碼:ide
/** * 動態代理 */ public class DynamicProxyCompanyC implements InvocationHandler { // 被代理的對象,即真實對象 private Object factory; public Object getFactory() { return factory; } public void setFactory(Object factory) { this.factory = factory; } // 經過proxy獲取動態代理的對象 public Object getProxyInstance() { //第三個參數是InvocationHandler,傳入自身說明此proxy對象是和自身的invoke方法合做的,代理對象方法調用會通過下面invoke的加強 return Proxy.newProxyInstance(factory.getClass().getClassLoader(), factory.getClass().getInterfaces(), this); } @Override /**經過動態代理對象對方法進行加強 * @param proxy 代理對象 * @param method 要加強的方法(攔截的方法) * @param args 方法參數 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { dosomeThingBefore(); Object ret = method.invoke(factory, args);// 經過反射機制調用方法 dosomeThingAfter(); return ret; } public void dosomeThingBefore() { System.out.println("售前服務,負責產品調研,興趣愛好"); } public void dosomeThingAfter() { System.out.println("售後服務,包裝丶送貨上門一條龍服務"); } }
測試類:測試
public class Proxytest { public static void main(String[] args) { // 代購公司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); } } // 售前服務,負責產品調研,興趣愛好 // A工廠出售男性用品,D罩杯 // 售後服務,包裝丶送貨上門一條龍服務 // -------------- // 售前服務,負責產品調研,興趣愛好 // B工廠生產女性用品,長度1.8米 // 售後服務,包裝丶送貨上門一條龍服務
1.實現了InvocationHandler接口;this
2.經過proxy獲取動態代理的對象。spa
根據咱們此例子裏面來講,動態代理就相似一個代購公司,可代購全部產品,須要購買哪一個產品的時候就實例化一個真實對象(如測試類須要男性用品則將接口引用指向真實對象AManFactory),根據真實對象建立代理對象來執行具體的方法,圖解以下:代理
接下來咱們先初步看一下JDK裏面的Proxy這個源碼。
這個註釋是說Proxy提供個一個靜態方法來建立代理類和代理實例,它也是全部由此方法建立的代理類的父類。
靜態方法建立代理實例即方法newProxyInstance(ClassLoader loader,Class<?>[]interfaces,InvocationHandler h);調試
InvocationHandler 是一個接口,定義了invoke(Object proxy, Method method, Object[] args)方法code
總的來講Proxy專門負責new一個實例(真實對象),而具體方法作什麼,業務怎樣加強就由InvocationHandler(抽象對象)的invoke方法(抽象對象即接口定義的方法)來決定。對象
接下來咱們要搞清楚動態代理的底層原理,首先咱們調試一下test類,會發現 ManToolFactory proxyObject = (ManToolFactory) proxy.getProxyInstance()中建立的proxyObject 對象類名是$Proxy0,是ManToolFactory接口的實現類。可是咱們項目工程裏面卻沒有$Proxy0這個類,那它到底是怎麼出現的,下節講解。接口