JAVA代理方式使用示例總結
一、 代理方式概括
Java的代理方式主要包含了靜態代理,動態代理兩種方式,其中,動態代理根據實現的方式不同,又可以划分為jdk動態代理和cglib動態代理.
二、 代理方式實現
1. 靜態代理
靜態代理,主要包含兩個實例,被代理類和代理類,兩者都要實現公共的接口,能夠面向接口實現,把被代理類組合到代理類中,在被代理類的本身功能上,加上代理類的自己的處理邏輯,達到增強的效果,就簡單的實現了代理功能.靜態代理只能事先編寫好代理代碼,經過統一編譯后才能執行.下面簡單的代碼實現:
1.1建立公共的接口
package jdkcglib.dynmicagent; /** * 〈一句話功能簡述〉<br> * 〈功能詳細描述〉 * * @author 12061799 * @see [相關類/方法](可選) * @since [產品/模塊版本] (可選) */ public interface IBookFacade { /** * * 功能描述: <br> * 〈功能詳細描述〉 * * @see [相關類/方法](可選) * @since [產品/模塊版本](可選) */ void addBook(String name); /** * * 功能描述: <br> * 〈功能詳細描述〉 * * @see [相關類/方法](可選) * @since [產品/模塊版本](可選) */ void deleteBook(); }
1.2建立被代理類
package jdkcglib.dynmicagent; /** * 〈一句話功能簡述〉<br> * 〈功能詳細描述〉 * * @author 12061799 * @see [相關類/方法](可選) * @since [產品/模塊版本] (可選) */ public class BookFacade implements IBookFacade { @Override public void addBook(String name) { System.out.println("增加圖書!"+name); } @Override public void deleteBook() { System.out.println("刪除圖書!"); } }
1.3建立代理類
package com.lilin.maven.service; /** * @author lilin * */ public class BookFacadeProxy implements IBookFacade { private BookFacade bookFacade; public BookFacadeProxy(BookFacade bookFacade) { this.bookFacade = bookFacade; } @Override public void addBook(String name) { System.out.println("新增之前。。。"); bookFacade.addBook("紅樓夢"); System.out.println("新增之后。。。"); } @Override public void deleteBook() { System.out.println("刪除之前。。。"); bookFacade.deleteBook(); System.out.println("刪除之后。。。"); } }
1.4建立測試類
package jdkcglib.dynmicagent; /** * 〈一句話功能簡述〉<br> * 〈功能詳細描述〉 * * @author 12061799 * @see [相關類/方法](可選) * @since [產品/模塊版本] (可選) */ public class Test { /** * 功能描述: <br> * 〈功能詳細描述〉 * * @param args * @see [相關類/方法](可選) * @since [產品/模塊版本](可選) */
public static void main(String[] args) {
BookFacadeProxy proxy = new BookFacadeProxy(new BookFacade());
proxy.addBook("紅樓夢");
proxy.deleteBook();
}
}
2. 動態代理---jdk動態代理(InvocationHandler 接口)
依據java的反射機制動態生成.在運行期間可以動態生成被代理類的實例.利用反射。獲取托付類的類載入器。托付類的全部接口,實例化代理類。通過反射類Proxy以及InvationHandler回調接口實現的。可是動態代理類僅僅能對該類所實現的接口中的方法進行代理。具有一定的局限性,而且反射的效率也不是非常高。下面是簡單的代碼實現:
2.1 建立公共接口類
package jdkcglib.dynmicagent; /** * 〈一句話功能簡述〉<br> * 〈功能詳細描述〉 * * @author 12061799 * @see [相關類/方法](可選) * @since [產品/模塊版本] (可選) */ public interface IBookFacade { /** * * 功能描述: <br> * 〈功能詳細描述〉 * * @see [相關類/方法](可選) * @since [產品/模塊版本](可選) */ void addBook(String name); /** * * 功能描述: <br> * 〈功能詳細描述〉 * * @see [相關類/方法](可選) * @since [產品/模塊版本](可選) */ void deleteBook(); }
2.2 建立被代理類
package jdkcglib.dynmicagent; /** * 〈一句話功能簡述〉<br> * 〈功能詳細描述〉 * * @author 12061799 * @see [相關類/方法](可選) * @since [產品/模塊版本] (可選) */ public class BookFacade implements IBookFacade { @Override public void addBook(String name) { System.out.println("新增加圖書!"+name); } @Override public void deleteBook() { System.out.println("直接刪除圖書!"); } }
2.3 建立代理類
package jdkcglib.dynmicagent; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * 〈一句話功能簡述〉<br> * 〈功能詳細描述〉 * * @author 12061799 * @see [相關類/方法](可選) * @since [產品/模塊版本] (可選) */ public class BookFacadeProxy implements InvocationHandler { /** * 被代理對象 */ private Object target; /** * * 功能描述: <br> * 〈功能詳細描述〉綁定被代理對象 返回代理對象 * * @param target * @return * @see [相關類/方法](可選) * @since [產品/模塊版本](可選) */ public Object bind(Object target) { this.target = target; // 要綁定接口(這是一個缺陷,cglib彌補了這一缺陷) // 返回代理對象 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; if (method.getName().startsWith("delete")) { System.out.println("#####方法執行之前#####"); result = method.invoke(target, args); System.out.println("#####方法執行之后#####"); } else { result = method.invoke(target, args); } return result; } }
2.4 建立測試類
package jdkcglib.dynmicagent; /** * 〈一句話功能簡述〉<br> * 〈功能詳細描述〉 * * @author 12061799 * @see [相關類/方法](可選) * @since [產品/模塊版本] (可選) */ public class Test { /** * 功能描述: <br> * 〈功能詳細描述〉 * * @param args * @see [相關類/方法](可選) * @since [產品/模塊版本](可選) */ public static void main(String[] args) { BookFacadeProxy proxy = new BookFacadeProxy(); IBookFacade bookProxy = (IBookFacade) proxy.bind(new BookFacade()); bookProxy.addBook("紅樓夢"); bookProxy.deleteBook(); } }
3. 動態代理---CGLIB動態代理(MethodInterceptor 接口)
CGLib (Code Generation Library) 是一個強大的,高性能,高質量的Code生成類庫。它能夠在執行期擴展Java類與實現Java接口。不僅僅能夠接管接口類的方法,同時還能夠接管普通類的方法.解決了jdk代理的只能代理接口類方法的難處,CGLib 的底層是Java字節碼操作框架(ASM).動態的生成被代理類的子類, 增強的代碼是硬編碼在新生成的類文件內部的,不會存在反射的性能問題.下面是簡單的代碼實現:
3.1 建立被代理類
package jdkcglib.cglib; /** * 〈一句話功能簡述〉<br> * 〈功能詳細描述〉 * * @author 12061799 * @see [相關類/方法](可選) * @since [產品/模塊版本] (可選) */ public class BookFacade { public void addBook() { System.out.println("增加圖書的普通方法..."); } }
3.2 建立代理類
package jdkcglib.cglib; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; /** * 〈一句話功能簡述〉<br> * 〈功能詳細描述〉 * * @author 12061799 * @see [相關類/方法](可選) * @since [產品/模塊版本] (可選) */ 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; } }
3.3 建立測試類
package jdkcglib.cglib; import java.io.UnsupportedEncodingException; /** * * 〈一句話功能簡述〉<br> * 〈功能詳細描述〉 * * @author 12061799 * @see [相關類/方法](可選) * @since [產品/模塊版本] (可選) */ public class TestCglib { /** * * 功能描述: <br> * 〈功能詳細描述〉 * * @param args * @throws UnsupportedEncodingException * @see [相關類/方法](可選) * @since [產品/模塊版本](可選) */ public static void main(String[] args) throws UnsupportedEncodingException { BookFacadeCglib cglib = new BookFacadeCglib(); BookFacade bookCglib = (BookFacade) cglib.getInstance(new BookFacade()); bookCglib.addBook(); } }
三、 java代理小結
靜態代理: 代理類就是通過調用被代理類的方法進行執行的,自己本身並不用清楚被代理類的方法.需要編譯后執行.耦合比較緊密.
JDK動態代理: 利用反射原理,動態的生成代理類,將類的載入延遲到程序執行之中,解耦了代理類和被代理類的聯系.主要要實現InvationHandler接口.
CGLIB動態代理:原理是繼承,把被代理類作為父類,動態生成被代理類的子類,三個步驟,設置父類,設置回調函數,創建子類.實現MethodInterceptor 接口,攔截調用父類方法時,會處理回調方法,處理自己的增強方法.
參考:
http://www.cnblogs.com/bhlsheji/p/5316693.html