JDK的Proxy動態代理模式和CGLIB動態代理模式的區別和共同點
首先我們來談談聯眾代理模式的不同之處:
《1》代理類不同點:
(1)Proxy的代理類的建立是通過工具類或者工廠類自動建立的,
我們只需要呼叫Proxy.newProxyInstance(Loader,interfaces,h);正確的傳入相應的引數,就可以得到餓哦們想要的目標類的代理類,這裡對這三個引數做一下簡單的介紹:Loader是目標類的類載入器,Interfaces是目標類實現的所有介面,h,是委託類物件。程式碼如下:
//動態生成代理物件
ISomeService someServiceImpl = (ISomeService) Proxy.newProxyInstance(
//目標類的類載入器 、
target.getClass().getClassLoader(),
//目標類實現的所有介面
target.getClass().getInterfaces(),
//代理類的委託物件
new ServiceProxyEntrust(target));
(1)Cglib的代理模式中,並沒有提供現成的工具或者工廠 類讓我們直接得到代理類,需要我們程式設計師手工定義類和方法來建立我們所需要的代理類,一般我個人喜歡把代理類的名字定義成“cglibProxy”,方法簽名定義成“newProxyInstance“,
CglibProxy.newProxyInstance(target.getClass(),mi);
target是我們的目標類,mi是我們的委託類物件。我們手工定義的工廠類的需要實現這個newProxyInstance()方法,並且在這個方法的內部,我們需要藉助增強器Enhancer來為我們的代理類指定目標類,並且讓委託類和目標類發生聯絡,具體的程式碼實現如下:
package com.abc.utils;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;//手工編寫的工具類,用於建立我們的代理物件
public class CglibProxy {
//建立代理物件的過程中,我們需要藉助一個類
//target:是我們的目標類
//mi:是我們的委託類物件
public static Object newProxyInstance(Class<?> target, MethodInterceptor mi) {
//增強器
Enhancer enhancer = new Enhancer();
//指定父類,即指定目標類
enhancer.setSuperclass(target);
//指定回撥物件,即指定代理類
//把目標類和委託類聯絡在了一起
enhancer.setCallback(mi);
//建立並且返回代理物件
return enhancer.create();
}}
通過這種方法,Cglib也可以一般性的建立代理類,但是我們之前說過,我們需要個性化的增強目標類,所以我們還應該讓這個目標類變得不一般,這就涉及到我們要說的第二點的不同,
《2》委託類的不同
(2)Proxy 的委託類需要實現InvocationHandler介面,該介面只有一個方法,我們需要重寫這個方法,
publci Object invoke(Object proxy,Method method,Object[] args);該方法的功能就是通過植入交叉邏輯程式碼。來達到個性化增強目標類的目的。(proxy是代理物件,method,是目標方法,args是目標方法的引數)程式碼如下:
/**
* proxy:代理物件
* method:目標方法
* args:目標方法的引數
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//植入交叉邏輯
SystemUtil.doTx();
//通過反射執行目標方法
Object result = method.invoke(target, args);
//植入交叉邏輯
SystemUtil.doLog();
return result;
}
(2)Cglib的委託類需要實現的介面是MethodInterceptor,然後需要重寫該介面中的intercept() 方法,程式碼如下:
/**
* obj:代理物件
* method:目標方法
* args:目標方法的引數
* proxy:目標方法的代理物件
*/
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
//植入交叉邏輯
SystemUtil.doTx();
//通過反射執行目標方法
Object result = method.invoke(target, args);
//植入交叉邏輯
SystemUtil.doLog();
return result;
==================================================
小結:二者的不同之處在於
(1)Proxy的代理類是有工具類或者工廠類動態的生成(我們只需要呼叫相應的方法,然後正確的傳入引數即可,具體的生成過程可以通過debug模式檢視)
Cglib是沒有提供相應的工具類,需要程式設計師手工編寫,
(2)二者的委託類實現的介面不同,所以重寫的的介面也不同
(3)Proxy 動態代理要求目標類必須是要實現介面的類,而Cglib的目標類可以不用實現介面(當然了實現了介面的目標類也同樣可以適用,用法和沒有實現介面的類似),但是Cglib的目標類是不能被final所修飾的,且必須提供無參的構造器(因為Cglib的代理類其實是目標類的子類)
============================
相同點:
(1)二者都可以在不修改目標類的原始碼的情況下,達到個性化增強目標類的業務邏輯功能的目的。
(2)二者的委託類雖然實現的介面和方法不同,但是這兩個重寫的方法的功能相同,都是通過在目標方法的前後執行交叉程式碼邏輯(或者是系統及服務)來達到增加目標方法的作用。