代理模式是Java常見的設計模式,代理類和爲拖類功能相同,代理類負責加強功能,代理類的對象自己並不真正實現服務,而是經過調用委託類的對象的相關方法,來提供特定的服務。 就像Spring Aop的實現,再特定方法執行前或後執行特定的攔截器,使用的就是動態代理。 代理分爲兩種: 靜態代理:由程序員建立或特定工具自動生成源代碼,再對其編譯。在程序運行前,代理類的.class文件就已經存在了。 動態代理:程序運行過程當中,由反射機制動態建立而成。java
下面分別討論靜態代理、jdk動態代理和cglib動態代理,Book.java和BookImpl.java爲三種代理方法的公共類,直接上代碼: 一、Book.java package com.proxy; public interface Book { //定義圖書添加接口 public void addBook(); } 2.BookImpl.java package com.proxy; //委託類,包括業務邏輯 public class BookImpl implements Book{ @Override public void addBook() { System.out.println("添加圖書"); } } 靜態代理類: //這是一個代理類,加強BookImpl功能 public class BookProxy implements Book{程序員
private BookImpl bookImpl; public BookProxy(BookImpl bookImpl) { this.bookImpl = bookImpl; } @Override public void addBook() { System.out.println("代理前"); bookImpl.addBook(); System.out.println("代理後"); }
} Test.java public class Test { public static void main(String[] args) { BookProxy proxy = new BookProxy(new BookImpl()); proxy.addBook(); }編程
} 輸出結果爲: 代理前 添加圖書 代理後 觀察代碼能夠發現每個代理類只能爲一個接口服務,這樣一來程序開發中必然會產生過多的代理,並且,全部的代理操做除了調用的方法不同以外,其餘的操做都同樣,則此時確定是重複代碼。解決這一問題最好的作法是能夠經過一個代理類完成所有的代理功能,那麼此時就必須使用動態代理完成。 Jdk動態代理設計到一個接口和一個類: InvocationHandler接口: public interface InvocationHandler { public Object invoke(Object proxy,Method method,Object[] args) throws Throwable; } Proxy類: Proxy類是專門完成代理的操做類,能夠經過此類爲一個或多個接口動態地生成實現類,此類提供了以下的操做方法: public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException 與靜態代理類對照的是動態代理類,動態代理類的字節碼在程序運行時由Java反射機制動態生成,無需程序員手工編寫它的源代碼。動態代理類不只簡化了編程工做,並且提升了軟件系統的可擴展性,由於Java 反射機制能夠生成任意類型的動態代理類。java.lang.reflect 包中的Proxy類和InvocationHandler 接口提供了生成動態代理類的能力 jdk動態代理示例:設計模式
public class BookProxy implements InvocationHandler{ide
private Object target;
/** * 綁定委託對象並返回一個代理類 */
public Object bind(Object target){ this.target = target; //取得代理對象 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this); }工具
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; System.out.println("代理前"); result = method.invoke(target, args); System.out.println("代理後"); return result; }
Test.java public class TestProxy {this
public static void main(String[] args) { BookFacadeProxy proxy = new BookFacadeProxy(); BookFacade bookProxy = (BookFacade) proxy.bind(new BookFacadeImpl()); bookProxy.addBook(); }
} } 輸出結果爲: 代理前 添加圖書 代理後 可是,JDK的動態代理依靠接口實現,若是有些類並無實現接口,則不能使用JDK代理,這就要使用cglib動態代理了。 Cglib動態代理 public class BookProxy implements MethodInterceptor {設計
private Object target; /** * 建立代理對象 */ public Object getInstance(Object target){ this.target = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.target.getClass()); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { System.out.println("代理前"); arg3.invokeSuper(arg0, arg2); System.out.println("代理後"); return null; }
} Test.java public class Test {代理
public static void main(String[] args) { BookProxy cglib = new BookProxy(); BookImpl bookCglib = (BookImpl) cglib.getInstance(new BookImpl()); bookCglib.addBook(); }
} 輸出結果爲: 代理前 添加圖書 代理後code