Java與Spring的代理

1.靜態(tài)代理

靜態(tài)代理车吹,顧名思義,手動代碼代理醋闭。通過代理類實現(xiàn)被代理類的接口窄驹,進而完成代理過程。其實就是才能重寫了证逻,原本的接口方法乐埠,手動去在目標方法執(zhí)行前中后,進行切割囚企,進而實現(xiàn)代理丈咐。

public class TestStaticProxy {

    public static void main(String[] args) {
        IRegisterService iRegisterService = new RegisterServiceImpl();
        IRegisterService proxy = new RegisterServiceProxy(iRegisterService);
        proxy.register("RyanLee", "123");
    }
}
interface IRegisterService {
    void register(String name, String pwd);
}

class RegisterServiceImpl implements IRegisterService {
    @Override
    public void register(String name, String pwd) {
        System.out.println(String.format("【向數(shù)據(jù)庫中插入數(shù)據(jù)】name:%s,pwd:%s", name, pwd));
    }
}

class RegisterServiceProxy implements IRegisterService {
    IRegisterService iRegisterService;

    public RegisterServiceProxy(IRegisterService iRegisterService) {
        this.iRegisterService = iRegisterService;
    }

    @Override
    public void register(String name, String pwd) {
        System.out.println("[Proxy]一些前置處理");
        System.out.println(“開始執(zhí)行被代理的方法”);
        iRegisterService.register(name, pwd);
        System.out.println("[Proxy]一些后置處理");

    }
}

2.JDK代理

JDK代理龙宏,動態(tài)代理類和被代理類必須繼承同一個接口棵逊。動態(tài)代理只能對接口中聲明的方法進行代理,有一定限制烦衣。每一個動態(tài)代理實例都有一個關(guān)聯(lián)的InvocationHandler歹河。通過代理實例調(diào)用方法,方法調(diào)用請求會被轉(zhuǎn)發(fā)給InvocationHandler的invoke方法花吟。(這里就可以看出為啥在實例化代理類時秸歧,要傳入目標類的接口,這樣在代理類實現(xiàn)的invoke方法里可以直接執(zhí)行接口方法實現(xiàn)了目標類被代理的過程)衅澈。實際上我們發(fā)現(xiàn)JDK的動態(tài)代理是基于反射的键菱,而實現(xiàn)方式和靜態(tài)代理很像,那為啥又說是動態(tài)代理呢今布?其實经备,細心的小伙伴就已經(jīng)發(fā)現(xiàn),JDK動態(tài)代理這種方式是一種對目標方法的增強部默,他不關(guān)心你目標方法侵蒙,而是通過newProxyInstance方法來生成新的 \color{#2196F3}{實現(xiàn)接口}的代理對象,只管代理執(zhí)行傅蹂,此處解耦纷闺。而對比靜態(tài)代理就需要靜態(tài)代理類知道目標類的信息算凿,實現(xiàn)目標類的接口,限制很多犁功。而動態(tài)代理在實現(xiàn)代理的時候,是傳遞需要代理類,的實現(xiàn),無關(guān)接口 所以并不需要為每一種接口都寫一個代理類了氓轰。

 public static void main(String[] args) {
        Target tar = new Target();
        ProxyHandler handler = new ProxyHandler();
        BBQ proxy = (BBQ) handler.getProxy(tar);
        proxy.sayBBQ("LF");
    }

    static class Target implements BBQ {
        @Override
        public void sayBBQ(String s) {
            System.out.println("這是原方法執(zhí)行的 say bbq " + s);
        }
    }

    interface BBQ {
        void sayBBQ(String s);
    }

    static class ProxyHandler implements InvocationHandler {
        Object obj;

        public Object getProxy(Object obj) {
            this.obj = obj;
            Object o = Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
            return o;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            doBefore();
            Object result = method.invoke(obj, args);
            doAfter();
            return result;
        }

        private void doBefore() {
            Thread thread = Thread.currentThread();
            System.out.println("[Proxy]一些前置處理" + thread.getName() + " " + thread.getId());
        }

        private void doAfter() {
            System.out.println("[Proxy]一些后置處理");
        }
    }

3.cglib代理

JDK的動態(tài)代理機制只能代理實現(xiàn)了接口的類,而不能實現(xiàn)接口的類就不能實現(xiàn)JDK的動態(tài)代理浸卦,cglib是針對類來實現(xiàn)代理的署鸡,他的原理是對指定的目標類生成一個子類,并覆蓋其中方法實現(xiàn)增強限嫌,但因為采用的是繼承靴庆,所以不能對final修飾的類進行代理。

public static void main(String[] args) {
        Target tar = new Target();
        CGLIBProxyDemo handler = new CGLIBProxyDemo();
        Target proxy = (Target) handler.getProxy(tar);
        proxy.sayBBQ("cglib代理");
    }

    static class Target implements JDKProxyUtil.BBQ {
        @Override
        public void sayBBQ(String s) {
            System.out.println("這是原方法執(zhí)行的 say bbq " + s);
        }
    }

    interface BBQ {
        void sayBBQ(String s);
    }

    static class CGLIBProxyDemo implements MethodInterceptor {
        private Object target;

        public Object getProxy(Object obj) {
            this.target = obj;
            Enhancer enhancer = new Enhancer();
            //生成子類
            enhancer.setSuperclass(this.target.getClass());
            // 回調(diào)方法
            enhancer.setCallback(this);
            // 創(chuàng)建代理對象
            return enhancer.create();
        }

        @Override
        public Object intercept(Object obj, Method method, Object[] param, MethodProxy methodProxy) throws Throwable {
            doBefore();
            Object result = methodProxy.invokeSuper(obj, param);
            doAfter();
            return result;
        }

        private void doBefore() {
            Thread thread = Thread.currentThread();
            System.out.println("[Proxy]一些前置處理" + thread.getName() + " " + thread.getId());
        }

        private void doAfter() {
            System.out.println("[Proxy]一些后置處理");
        }


    }

結(jié)語

仔細觀察會發(fā)現(xiàn):\color{#2196F3}{代理}的原理依據(jù)萤皂,就是多態(tài)撒穷,要么實現(xiàn)接口生成代理類,要么繼承目標類生成代理類裆熙,而\color{#2196F3}{動態(tài)}的手段就是反射端礼,利用反射來獲取被代理類的信息,進而才能實現(xiàn)不需要了解目標信息來構(gòu)建多態(tài)入录,從而動態(tài)解耦蛤奥。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市僚稿,隨后出現(xiàn)的幾起案子凡桥,更是在濱河造成了極大的恐慌,老刑警劉巖蚀同,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缅刽,死亡現(xiàn)場離奇詭異,居然都是意外死亡蠢络,警方通過查閱死者的電腦和手機衰猛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刹孔,“玉大人啡省,你說我怎么就攤上這事∷柘迹” “怎么了卦睹?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長方库。 經(jīng)常有香客問我结序,道長,這世上最難降的妖魔是什么纵潦? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任徐鹤,我火速辦了婚禮配喳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘凳干。我一直安慰自己,他們只是感情好被济,可當我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布救赐。 她就那樣靜靜地躺著,像睡著了一般只磷。 火紅的嫁衣襯著肌膚如雪经磅。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天钮追,我揣著相機與錄音预厌,去河邊找鬼。 笑死元媚,一個胖子當著我的面吹牛轧叽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播刊棕,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼炭晒,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了甥角?” 一聲冷哼從身側(cè)響起网严,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嗤无,沒想到半個月后震束,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡当犯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年垢村,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片灶壶。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡肝断,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出驰凛,到底是詐尸還是另有隱情胸懈,我是刑警寧澤,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布恰响,位于F島的核電站趣钱,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏胚宦。R本人自食惡果不足惜首有,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一燕垃、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧井联,春花似錦卜壕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蚕脏,卻和暖如春侦副,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背驼鞭。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工秦驯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人挣棕。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓译隘,卻偏偏與公主長得像,于是被迫代替她去往敵國和親洛心。 傳聞我的和親對象是個殘疾皇子细燎,可洞房花燭夜當晚...
    茶點故事閱讀 43,658評論 2 350

推薦閱讀更多精彩內(nèi)容