標籤:ash 修改 控制 ext hashcode 對象 並且 gif exce
代理模式
在設計模式中存在的代理模式;代理模式的作用就是為其他對象提供一種代理以控制對這個對象的訪問。
代理模式一般存在三種角色:抽象角色,代理角色,真實角色;百度百科上摘抄了三種角色的解釋:
抽象角色:通過介面或抽象類別聲明真實角色實現的業務方法。 代理角色:實現抽象角色,是真實角色的代理,通過真實角色的商務邏輯方法來實現抽象方法,並可以附加自己的操作。 真實角色:實現抽象角色,定義真實角色所要實現的商務邏輯,供代理角色調用。 代理模式的優點:一是可以隱藏委託類(真實角色)的實現,二是可以實現客戶和委託類之間的解耦; Java中的代理
在java中代理分靜態代理和動態代理;所謂靜態代理是在程式運行前代理類就已經存在的,一般這種代理類都是通過我們自己定義的java類來實現;動態代理相對就麻煩一些,是在程式運行時組建代理程式類;是通過我們在Java代碼來動態產生的;
現在有個情境:火車站售票,有些代理點也可以買票,在這裡火車票代理點就是代理角色;
首先把賣票抽象成一個介面:
public interface iTicketService { void SellTicket(String name);}
火車站賣票實現這個介面:
public class trainStation implements iTicketService { public void SellTicket(String name) { System.out.println(name + "成功購買了一張票"); }}靜態代理
靜態代理就是在java代碼中我們自己定義代理類;代理類中持有委託類的引用;並且代理類也實現了和委託類一樣的介面;
public class stationProxy implements iTicketService { private iTicketService TicketService; public stationProxy(iTicketService ticketService) { this.TicketService = ticketService; } public void SellTicket(String name) { System.out.println("代售點開始賣票"); this.TicketService.SellTicket(name); System.out.println("代售點賣票成功"); }}
從代碼中我們可以看到代理的好處,代理內部還是調用委託類的方法,我們在調用委託類的方法前或是方法後可以來進行一些相關操作;
靜態代理的調用也非常的簡單:
iTicketService ticketService=new trainStation();stationProxy station=new stationProxy(ticketService);station.SellTicket("張三");
輸出:
代售點開始賣票
張三成功購買了一張票
代售點賣票成功
動態代理
動態代理相對於靜態代理的區別就在於代理類是在運行時產生的;動態代理的優勢就在於可以方便的對代理類的函數統一的管理,而不用一個個的去修改代理函數,當代理非常多的時候,動態代理的優勢就很多大了;
InvocationHandler
在使用動態代理時,需要我們定義一個代理類和委託類之間關聯的中介類,在java中這個中介類應該實現InvocationHandler介面;
public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;}
在InvocationHandler介面中只有一個invoke方法,當代理類執行代理方法都會通過invoke方法來執行;proxy:代理類對象,method 需要執行的代理方法;args代理方法執行的參數,方法的傳回值object也就是代理方法的傳回值,我們可以在invoke方法內添加統一的處理邏輯;比如火車票代售點我們可以建立動態代理類:
public class dynamicProxy implements InvocationHandler { private iTicketService TicketService; public dynamicProxy(iTicketService ticketService){ this.TicketService=ticketService; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("動態代理開始賣票"); Object obj= method.invoke(TicketService,args); System.out.println("動態代理賣票結束"); return obj; }}
從dynamicProxy類來看,我們的代理類也持有委託類的一個執行個體,在 invoke中採用反射進行方法的執行;
在JAVA中實現了InvocationHandler介面的動態代理類需要藉助Proxy擷取執行個體
dynamicProxy dynamicProxy=new dynamicProxy(ticketService); Class<?>[] interfaces=new Class<?>[]{iTicketService.class}; System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true"); iTicketService ticketproxy=(iTicketService)Proxy.newProxyInstance(iTicketService.class.getClassLoader(),interfaces,dynamicProxy); ticketproxy.SellTicket("李四");
在Proxy類中通過newProxyInstance來擷取代理類的執行個體;
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)
在newProxyInstance方法中ClassLoader是代理載入類,interfacess數組是類實現的介面數組,h就是我們自己定義的中介類了
通過System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");方法會產生一個$Proxy0.class檔案,這個檔案即為動態產生的代理類檔案;
我們可以看下產生的代理類:
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.lang.reflect.UndeclaredThrowableException;public final class $Proxy0 extends Proxy implements iTicketService { private static Method m1; private static Method m2; private static Method m3; private static Method m0; public $Proxy0(InvocationHandler var1) throws { super(var1); } public final boolean equals(Object var1) throws { try { return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue(); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final String toString() throws { try { return (String)super.h.invoke(this, m2, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final void SellTicket(String var1) throws { try { super.h.invoke(this, m3, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final int hashCode() throws { try { return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue(); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")}); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); m3 = Class.forName("iTicketService").getMethod("SellTicket", new Class[]{Class.forName("java.lang.String")}); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } }}View Code
在產生的代理類中m3就是我們的介面定義的SellTicket方法,內部還是調用了InvocationHandler介面中的invoke方法;
Java中的代理