標籤:
1.什麼是代理
代理模式是常用的Java 設計模式,它的特徵是代理類與委託類有同樣的介面,代理類主要負責為委託類預先處理訊息、過濾訊息、把訊息轉寄給委託類,以及事後處理訊息等。
2.什麼是動態代理
在程式運行時,運用反射機制動態建立代理執行個體對象。JDK的動態代理機制只能代理實現了介面的類,而不能實現介面的類就不能實現JDK的動態代理。
相關類與介面
java.lang.reflect.Proxy:這是 Java 動態代理機制的主類,它提供了一組靜態方法來為一組介面動態地組建代理程式類及其對象。 // 方法:該方法用於為指定類裝載器、一組介面及調用處理器產生動態代理類執行個體static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)java.lang.reflect.InvocationHandler:這是調用處理器介面,它自訂了一個 invoke 方法,用於集中處理在動態代理類對象上的方法調用,通常在該方法中實現對委託類的代理訪問。 //方法:調用處理器根據這三個參數進行預先處理或指派到委託類執行個體上發射執行Object invoke(Object proxy, Method method, Object[] args)
3.動態代理樣本
代理類public class LogHandler implements InvocationHandler { private Object targetObject; public Object newProxyInstance(Object targetObject) { this.targetObject = targetObject; return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("start-->>" + method.getName()); for (int i=0; i<args.length; i++) { System.out.println(args[i]); } Object ret = null; try { //調用目標方法 ret = method.invoke(targetObject, args); System.out.println("success-->>" + method.getName()); }catch(Exception e) { e.printStackTrace(); System.out.println("error-->>" + method.getName()); throw e; } return ret; }}
介面類public interface UserManager { public void addUser(String userId, String userName);}
目標類package com.bjpowernode.pattern;public class UserManagerImpl implements UserManager { public void addUser(String userId, String userName) { //System.out.println("start-->>addUser() userId-->>" + userId); try { System.out.println("AddUser" );} }}
用戶端public class Client { /** * @param args */ public static void main(String[] args) { LogHandler logHandler = new LogHandler(); UserManager userManager = (UserManager)logHandler.newProxyInstance(new UserManagerImpl()); userManager.addUser("0001","張三"); }}
4.動態代理類與靜態代理的區別:
由程式員建立或由特定工具自動產生原始碼,再對其編譯。在程式運行前,代理類的.class檔案就已經存在了。動態代理類:在程式運行時,運用反射機制動態建立而成。無需程式員手工編寫它的原始碼。動態代理類不僅簡化了編程工作,而且提高了軟體系統的可擴充性,因為Java 反射機制可以產生任意類型的動態代理類。
5.動態類的應用情境
不允許直接存取某些類;對訪問要做特殊處理等。或者,要對原方法進行統一的擴充,例如加入日誌記錄。
6.什麼是CGLIB動態代理
JDK的動態代理機制只能代理實現了介面的類,而不能實現介面的類就不能實現JDK的動態代理,cglib是針對類來實現代理的,他的原理是對指定的目標類產生一個子類,並覆蓋其中方法實現增強,但因為採用的是繼承,所以不能對final修飾的類進行代理。
7.CGLIB樣本
委託類:
package com.orient.cglib;public class BookFacadeImpl1 { public void addBook() { System.out.println("增加圖書的普通方法..."); } }
代理類
package com.orient.cglib;import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;public class BookFacadeCglib implements MethodInterceptor { private Object target; /** * 建立代理對象 * * @param target * @return */ 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 obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("事物開始"); proxy.invokeSuper(obj, args); System.out.println("事物結束"); return null; } }
測試類別
package com.orient.cglib;public class TestCglib { public static void main(String[] args) { BookFacadeCglib cglib=new BookFacadeCglib(); BookFacadeImpl1 bookCglib=(BookFacadeImpl1)cglib.getInstance(new BookFacadeImpl1()); bookCglib.addBook(); } }
這個工程依賴於cglib.jar 和asm.jar
JAVA動態代理詳解