標籤:java
接著上篇部落格的代理模式,我們繼續,上篇部落格介紹了JDK的動態代理,但是JDK的動態代理機制只能代理實現了介面的類,而不能實現介面的類就不能實現JDK的動態代理,這樣就存在一定的局限性。對於這種情況,我們採用CGLIB來實現。
一、CGLIB動態代理
cglib是針對類來實現代理的,其實現原理:CGLIB的底層採用ASM位元組碼產生架構,使用位元組碼技術組建代理程式,比使用反射組建代理程式的效果要高,是對指定的目標類產生一個子類,並覆蓋其中方法實現增強。但是也有一點點不足,因為採用的是繼承,所以不能對final修飾的類進行代理。
還是使用以前的代碼,依然還是簡單的三步來實現。第一:建立一個普普通通的業務類;第二:寫CGLIB代理類;第三:寫測試代碼或者用戶端調用。這裡的不同是第一步中,我們不需要在建介面了,只是一個普普通通的java類。
看代碼:
<span style="font-family:KaiTi_GB2312;font-size:18px;"> /** * 業務類(包含商務邏輯) * 即:委託類 * @author Cassie */ public class Account{ @Override public void queryAccount() { System.out.println("查詢方法..."); } @Override public void updateAccount() { System.out.println("修改方法..."); } }</span> 然後,我們來寫CGLIB代理類:
<span style="font-family:KaiTi_GB2312;font-size:18px;">import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; /** * 使用cglib動態代理 * @author Cassie * 實現MethodInterceptor 介面 */ public class CglibProxy 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("before"); Object result = proxy.invokeSuper(obj, args); System.out.println("after"); return result } } </span> 最後寫測試類別調用
<span style="font-family:KaiTi_GB2312;font-size:18px;">public class TestCglib { public static void main(String[] args) { //執行個體化代理 CglibProxy cglib=new CglibProxy(); //通過代理拿到對象 Account account = (Account)cglib.getInstance(new Account()); account.query(); } }</span>
通過以上代碼,我們發現proxy.invokeSuper(obj,arg)是執行的關鍵。
使用CGLIB,需要實現 CGLib 給我們提供的 MethodInterceptor 實作類別,並填充 intercept() 方法。方法中最後一個 MethodProxy 類型的參數 proxy,值得注意!CGLib 給我們提供的是方法層級的代理,也可以理解為對方法的攔截。我們直接調用 proxy 的 invokeSuper() 方法,將被代理的對象 obj 以及方法參數 args 傳入其中即可。
至此,CGLIB代理也實現了。
談談java的代理模式認識 三————CGLIB代理