給某個對象提供一個代理對象,由代理對象控制對原對象的引用。java
1.適配器模式:適配器模式改變對象的接口,代理模式不改變接口。node
2.裝飾器模式:裝飾者模式是爲了增長功能,代理模式是爲了控制。ide
1.中介隔離:隔離訪問,原對象不能被直接引用時,代理對象能夠經過實現相同的接口來間接提供給客戶訪問。函數
2.功能加強:擴展原對象的功能。主要負責預處理,過濾,過後對返回結果的處理。好比日誌功能,解決亂碼問題。工具
按代理建立的時期,分爲靜態代理,動態代理。測試
靜態代理是在源碼上建立,並對其編譯。this
動態代理是在程序運行時,經過反射機制動態建立。代理
1.建立服務接口日誌
public interface Machine { void run(); }
2.建立原對象code
public class RealMachine implements Machine { private String machineName; public RealMachine(String machineName){ this.machineName = machineName; init(); } @Override public void run() { System.out.println("run " + machineName); } private void init(){ System.out.println("init "+machineName); } }
3.建立代理對象
public class ProxyMachine implements Machine{ private RealMachine realMachine; private String machineName; public ProxyMachine(String machineName){ this.machineName = machineName; } @Override public void run() { if(realMachine == null){ realMachine = new RealMachine(machineName); } System.out.println("start run"); realMachine.run(); System.out.println("stop run"); } }
4.測試
@Test public void testStaticMachine(){ Machine machine = new ProxyMachine("robot 001"); machine.run(); }
每個原對象都要建立一個代理類,不適合
1.建立動態代理類
public class DynamicProxyHandler implements InvocationHandler{ private Object object; public DynamicProxyHandler(final Object object){ this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("start proxy run"); Object invoke = method.invoke(object, args); System.out.println("stop proxy run"); return invoke; } }
2.測試
@Test public void testDynamicMachine(){ Machine machine = new RealMachine("robot 002"); Machine proxyMachine = (Machine) Proxy.newProxyInstance( Machine.class.getClassLoader(), new Class[]{Machine.class}, new DynamicProxyHandler(machine)); proxyMachine.run(); }
代理包:java.lang.reflect.Proxy
JDK動態代理須要使用newProxyInstance方法.
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )
三個參數:
1.ClassLoader loader: 指定當前目標對象使用類加載器,獲取加載器的方法是固定的
2.Class<?>[] interfaces: 目標對象實現的接口的類型,使用泛型方式確認類型
3.InvocationHandler h 事件處理,執行目標對象的方法時,會觸發事件處理器的方法,會把當前執行目標對象的方法做爲參數傳入
1.建立代理工廠
public class ProxyFactory { private Object object; public ProxyFactory(Object object){ this.object = object; } public Object getProxyInstance(){ return Proxy.newProxyInstance( object.getClass().getClassLoader(), object.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("start proxyFactory"); Object invoke = method.invoke(object, args); System.out.println("stop proxyFactory"); return invoke; } } ); } }
2.測試
@Test public void testProxyFactory(){ Machine machine = new RealMachine("robot 003"); Machine proxyInstance = (Machine) new ProxyFactory(machine).getProxyInstance(); proxyInstance.printMessage("test"); }
和JDK代理不一樣,當目標對象沒有實現任何接口時,cglib代理能夠對目標對象進行代理。
cglib代理,又名子類代理。它是在內存中構建一個子類對象,從而實現對目標對象功能的擴展。
1.依賴包
asm-2.2.3,asm-commons-2.2.3,asm-util-2.2.3 ,cglib-nodep-2.1_3
2.建立實體
public class CglibMachine{ private RealMachine realMachine; private String machineName; public CglibMachine(){ } public CglibMachine(String machineName){ this.machineName = machineName; } public void run() { if(realMachine == null){ realMachine = new RealMachine(machineName); } System.out.println("start run"); realMachine.run(); System.out.println("stop run"); } }
3.建立工廠
public class CglibProxyFactory implements MethodInterceptor{ private Object object; public CglibProxyFactory(Object object){ this.object = object; } //給目標對象建立一個代理對象 public Object getProxyInstance(){ //工具類 Enhancer enhancer = new Enhancer(); //設置父類 enhancer.setSuperclass(object.getClass()); //設置回調函數 enhancer.setCallback(this); //建立子類 return enhancer.create(); } @Override public Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("start cglib proxy"); //執行目標對象方法 Object invoke = method.invoke(object, args); System.out.println("stop cglib proxy"); return invoke; } }
4.測試
@Test public void testCglibFactory(){ CglibMachine machine = new CglibMachine("robot 004"); CglibMachine proxyInstance = (CglibMachine) new CglibProxyFactory(machine).getProxyInstance(); proxyInstance.run(); }