標籤:int method system water tar sele glib 編譯 log
思考:在IBuyWatermelon添加一個方法selectWatermelon()
靜態代理中需要在RealSubject中實現該方法,而且Proxy也要實現該方法調用RealSubject中的實現,如果再增加10個方法還是得這樣操作,導致大量的代碼重複。
現在來看動態代理(顧名思義,是在運行時才形成的代理對象,不像靜態代理在編譯時間就載入代理對象)。
產生動態代理的方法有很多: JDK中內建的動態代理java.lang.reflect.*, CGlib等
下面的例子是JDK中內建的動態代理java.lang.reflect.*
IBuyWatermelon():介面
package com.maggie.dynamicproxy;public interface IBuyWatermelon { //代理事件 public abstract String buyWatermelon(); public abstract void selectWatermelon();}
BuyWatermelonImpl:實作類別
package com.maggie.dynamicproxy;//可理解成被代理者public class BuyWatermelonImpl implements IBuyWatermelon { private Supermarket supermaket; public BuyWatermelonImpl(Supermarket supermaket) { super(); this.supermaket = supermaket; } @Override public String buyWatermelon() { System.out.println("在"+supermaket.getName()+" 買西瓜"); return "watermelon"; } @Override public void selectWatermelon() { System.out.println("選擇無籽西瓜"); }}
ProxyFactory:代理對象類(核心代碼)
package com.maggie.dynamicproxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class ProxyFactory { //維護一個目標對象 private Object target; public ProxyFactory(Object target){ this.target=target; } //給目標對象組建代理程式對象 public Object getProxyInstance(){ //動態代理的核心,涉及到反射 return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //執行目標對象方法 Object returnValue = method.invoke(target, args); return returnValue; } } ); }}
用戶端調用
package com.maggie.dynamicproxy;public class Main { public static void main(String[] args) { Supermarket zhaoLiu = new Supermarket(); zhaoLiu.setName("趙六超市"); IBuyWatermelon target = new BuyWatermelonImpl(zhaoLiu);//被代理的對象 //建立代理對象 IBuyWatermelon hourskeeper = (IBuyWatermelon) new ProxyFactory(target).getProxyInstance(); hourskeeper.buyWatermelon(); hourskeeper.selectWatermelon(); }}
輸出
在趙六超市 買西瓜選擇無籽西瓜
現在就算IBuyWatermelon的方法再怎麼增加,也只需要在BuyWatermelonImpl實現,就可以在用戶端調用,不會出現大量的重複代碼。
從靜態代理到動態代理都圍繞著賣瓜事件,為了前後方便比較,但是動態代理並沒完,裡面的源碼機制才是核心關鍵
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)這個方法是整個動態代理實現的關鍵
動態代理Java實現