代理模式

一呢蔫、簡介

代理模式是23種設(shè)計(jì)模式的一種,他是指一個(gè)對(duì)象A通過持有另一個(gè)對(duì)象B鹏氧,可以具有B同樣的行為的模式渤涌。為了對(duì)外開放協(xié)議,B往往實(shí)現(xiàn)了一個(gè)接口把还,A也會(huì)去實(shí)現(xiàn)接口实蓬。但是B是“真正”實(shí)現(xiàn)類,A則比較“虛”吊履,他借用了B的方法去實(shí)現(xiàn)接口的方法安皱。A雖然是“偽軍”,但它可以增強(qiáng)B艇炎,在調(diào)用B的方法前后都做些其他的事情酌伊。Spring AOP就是使用了動(dòng)態(tài)代理完成了代碼的動(dòng)態(tài)“織入”。

二缀踪、靜態(tài)代理和動(dòng)態(tài)代理

靜態(tài)代理:類A寫死持有B居砖,就是B的靜態(tài)代理;
動(dòng)態(tài)代理:如果A代理的對(duì)象是不確定的驴娃,就是動(dòng)態(tài)代理奏候。目前動(dòng)態(tài)代理分:JDK動(dòng)態(tài)代理,CGLIB動(dòng)態(tài)代理唇敞。

三蔗草、JDK動(dòng)態(tài)代理

  • 3.1 簡介
    jdk動(dòng)態(tài)代理是jre提供給我們的類庫,可以直接使用厚棵。不需要第三方提供
  • 3.2 代碼實(shí)現(xiàn)
  • 3.2.1 定義接口并實(shí)現(xiàn)接口

/**
 * 定義接口
 *
 * @author <a href="jian.huang@bintools.cn">yunzhe</a>
 * @version 1.0.0 2019-07-08-下午8:15
 */
public interface IUserManager {
    void addUser(String id,String password);
}  

import com.bintools.inteface.IUserManager;

/**
 * 接口實(shí)現(xiàn)
 *
 * @author <a href="jian.huang@bintools.cn">yunzhe</a>
 * @version 1.0.0 2019-07-08-下午8:16
 */
public class IUserManagerImpl implements IUserManager {
    @Override
    public void addUser(String id, String password) {
        System.out.println("=========添加用戶信息成功。蔼紧。婆硬。。==========");
    }
}
  • 3.2.2 實(shí)現(xiàn)jdk代理類奸例,主要是要實(shí)現(xiàn)InvocatinHandler類
mport java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * jdk代理模式
 *
 * @author <a href="jian.huang@bintools.cn">yunzhe</a>
 * @version 1.0.0 2019-07-08-下午8:17
 */
public class JDKProxy implements InvocationHandler {
    /** 需要代理的目標(biāo)對(duì)象**/
    private Object targetObject;

    /***
     * 將目標(biāo)對(duì)象傳入進(jìn)行代理
     * @param targetObject
     * @return
     */
    public Object newProxy(Object targetObject){
        this.targetObject = targetObject;
        //返回代理對(duì)象
        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(),this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //此部分進(jìn)行一定的邏輯處理
        checkPopedom();
        //設(shè)置返回方法的返回值
        Object ret =null;
        ret = method.invoke(targetObject,args);
        return ret;
    }

    private void checkPopedom() {
        System.out.println("========邏輯處理已完成=======");
    }
}
  • 3.2.3 定義客戶端
import com.bintools.inteface.IUserManager;
import com.bintools.inteface.impl.IUserManagerImpl;
import com.bintools.jdk.JDKProxy;

/**
 * 客戶端
 *
 * @author <a href="jian.huang@bintools.cn">yunzhe</a>
 * @version 1.0.0 2019-07-08-下午8:22
 */
public class Client {

    public static void main(String[] args) {
        System.out.println("**************JDKPROXY*************");
        JDKProxy jdkProxy = new JDKProxy();
        IUserManager iUserManager = (IUserManager) jdkProxy.newProxy(new IUserManagerImpl());
        iUserManager.addUser("100","one234#$%");
    }
} 
  • 3.2.4 執(zhí)行結(jié)果信息


    jdk動(dòng)態(tài)代理.jpg

    從上可知:JDK代理是不需要第三方支持的彬犯,只需要JDK環(huán)境姐可以進(jìn)行代理。使用條件:
    1) 實(shí)現(xiàn)InvocationHandler
    2 ) 使用Proxy.newProxyInstance產(chǎn)生代理對(duì)象
    3)被代理的對(duì)象必須要實(shí)現(xiàn)接口

  • 3.2.5 CGLIB動(dòng)態(tài)代理


import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * TODO
 *
 * @author <a href="jian.huang@bintools.cn">yunzhe</a>
 * @version 1.0.0 2019-07-08-下午8:36
 */
public class CglibProxy implements MethodInterceptor {
    /**CGLIB 需要代理的對(duì)象**/
    private Object targetObject;
    /**創(chuàng)建代理對(duì)象**/
    public Object createProxyObject(Object targetObject){
        this.targetObject = targetObject;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(targetObject.getClass());
        enhancer.setCallback(this);
        Object proxyO = enhancer.create();
        return proxyO;
    }
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        Object obj = null;
        /**檢測(cè)當(dāng)前方法是否是addUser**/
        if("addUser".equals(method.getName())){
            checkPepedom();
        }
        obj = method.invoke(targetObject,args);
        return obj;
    }
  /**可以做檢測(cè)或其他處理**/
    private void checkPepedom() {
        System.out.println("*******代理方法為addUser,進(jìn)行業(yè)務(wù)處理*******");
    }
}

結(jié)果展示:


cglib.jpg

從上可知:CGlib必須依賴與CGLIB的類庫查吊,待它需要類來實(shí)現(xiàn)任何接口代理的指定類生成一個(gè)子類谐区,覆蓋其中方法,是一種繼承但是針對(duì)接口編程的環(huán)境下推進(jìn)使用JDK代理逻卖。

四宋列、JDK與CGLIB動(dòng)態(tài)代理

  • 4.1 JDK動(dòng)態(tài)代理
    利用攔截器(攔截器必須實(shí)現(xiàn)InvocationHanlder)加上反射機(jī)制生成一個(gè)實(shí)現(xiàn)代理的匿名類
  • 4.2 CGLIB動(dòng)態(tài)代理
    利用第三方類庫,對(duì)代理對(duì)象類的class文件加載進(jìn)來评也,通過修改字節(jié)嗎生成子類來處理
  • 4.3 JDK動(dòng)態(tài)代理與CGLIB字節(jié)碼生成的區(qū)別
    1)JDK動(dòng)態(tài)代理只能對(duì)實(shí)現(xiàn)接口的類生成代理炼杖,而不能針對(duì)類
    2)CGLIB是針對(duì)類實(shí)現(xiàn)代理灭返,主要是指定的類生成子類,覆蓋其中的方法坤邪。并覆蓋其中方法實(shí)現(xiàn)增強(qiáng)熙含,但是因?yàn)椴捎美^承,所以類不要用final修飾
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末艇纺,一起剝皮案震驚了整個(gè)濱河市怎静,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌黔衡,老刑警劉巖蚓聘,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異员帮,居然都是意外死亡或粮,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門捞高,熙熙樓的掌柜王于貴愁眉苦臉地迎上來氯材,“玉大人,你說我怎么就攤上這事硝岗∏庀” “怎么了?”我有些...
    開封第一講書人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵型檀,是天一觀的道長冗尤。 經(jīng)常有香客問我,道長胀溺,這世上最難降的妖魔是什么裂七? 我笑而不...
    開封第一講書人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮仓坞,結(jié)果婚禮上背零,老公的妹妹穿的比我還像新娘。我一直安慰自己无埃,他們只是感情好徙瓶,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著嫉称,像睡著了一般侦镇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上织阅,一...
    開封第一講書人閱讀 52,255評(píng)論 1 308
  • 那天壳繁,我揣著相機(jī)與錄音,去河邊找鬼。 笑死氮趋,一個(gè)胖子當(dāng)著我的面吹牛伍派,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播剩胁,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼诉植,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了昵观?” 一聲冷哼從身側(cè)響起晾腔,我...
    開封第一講書人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎啊犬,沒想到半個(gè)月后灼擂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡觉至,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年剔应,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片语御。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡峻贮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出应闯,到底是詐尸還是另有隱情纤控,我是刑警寧澤,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布碉纺,位于F島的核電站船万,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏骨田。R本人自食惡果不足惜耿导,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望态贤。 院中可真熱鬧舱呻,春花似錦、人聲如沸抵卫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽介粘。三九已至,卻和暖如春晚树,著一層夾襖步出監(jiān)牢的瞬間姻采,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來泰國打工爵憎, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留慨亲,地道東北人婚瓜。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像刑棵,于是被迫代替她去往敵國和親巴刻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359