成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JDK的動(dòng)態(tài)代理

desdik / 3433人閱讀

摘要:實(shí)際開發(fā)中的,通用異常處理,通用日志處理,事物處理都可以用到動(dòng)態(tài)代理。四總結(jié)優(yōu)點(diǎn)動(dòng)態(tài)代理類簡(jiǎn)化了代碼編程工作,提高了軟件的可擴(kuò)展性。

JDK的動(dòng)態(tài)代理

一、靜態(tài)代理

了解動(dòng)態(tài)代理前,有必要先講解下靜態(tài)代理。

舉個(gè)例子:銀行開通了短信業(yè)務(wù),在你取錢,存錢,轉(zhuǎn)賬后都會(huì) 給你發(fā)送短信,我們來模擬下業(yè)務(wù)場(chǎng)景。

靜態(tài)代理的實(shí)現(xiàn)

下面來模擬下業(yè)務(wù)代碼

1.定義IBankCardService接口

/**
 * 銀行卡操作接口
 * @author yizl
 *
 */
public interface IBankCardService {
    
    /**
     * 存錢
     * @param cardId
     */
    public void putInMoney(String cardId);
    
    /**
     * 取錢
     * @param cardId
     */
    public void outMoney(String cardId);
    
    /**
     * 查詢余額
     * @param cardId
     */
    public String getMoney(String cardId);
}

2.接口實(shí)現(xiàn)(BankCardServiceImpl)

/**
 * 銀行卡操作實(shí)現(xiàn)類
 * @author yizl
 *
 */
public class BankCardServiceImpl implements IBankCardService {

    @Override
    public void putInMoney(String cardId) {
        System.out.println("開始往銀行卡賬號(hào)為:"+cardId+" 存錢");
    }

    @Override
    public void outMoney(String cardId) {
        System.out.println("向銀行卡賬號(hào)為:"+cardId+" 取錢");
    }

    @Override
    public String getMoney(String cardId) {
        System.out.println("查詢銀行卡賬號(hào)為:"+cardId+" 的余額");
        return null;
    }

}

3.編寫代理類

假設(shè)項(xiàng)目經(jīng)理有個(gè)需求:在每次業(yè)務(wù)操作后都需要向用戶發(fā)送短信.

在不修改已有的實(shí)現(xiàn)類的前提下怎么實(shí)現(xiàn)這個(gè)需求.

1.我們寫一個(gè)代理類,讓它與銀行卡操作實(shí)現(xiàn)類的接口相同.

2.在代理類的構(gòu)造器中,傳入銀行卡操作實(shí)現(xiàn)類,在代理類的方法內(nèi)部仍然調(diào)用銀行卡操作實(shí)現(xiàn)類的方法.

代理類

/**
 * 代理銀行卡操作實(shí)現(xiàn)類
 * @author yizl
 *
 */
public class ProxyBankCardServiceImpl implements IBankCardService {

    private IBankCardService bankCardService;
    
    public ProxyBankCardServiceImpl(IBankCardService bankCardService) {
        this.bankCardService=bankCardService;
    }

    @Override
    public void putInMoney(String cardId) {
        bankCardService.putInMoney(cardId);
        System.out.println("向客戶發(fā)送短信");
    }

    @Override
    public void outMoney(String cardId) {
        bankCardService.outMoney(cardId);
        System.out.println("向客戶發(fā)送短信");
    }

    @Override
    public String getMoney(String cardId) {
        bankCardService.getMoney(cardId);
        System.out.println("向客戶發(fā)送短信");
        return null;
    }
    
}

4.調(diào)用代理類

public class ProxyTest {

    public static void main(String[] args) {
        IBankCardService bankCardService =new BankCardServiceImpl();
        IBankCardService proxyBankCard=new ProxyBankCardServiceImpl(bankCardService);
        proxyBankCard.putInMoney("9527");
    }
    
}

打印結(jié)果:
    開始往銀行卡賬號(hào)為:9527的賬戶存錢
    向客戶發(fā)送短信

可以看出,代理類的作用:代理對(duì)象=增強(qiáng)代碼+目標(biāo)對(duì)象

代理類只對(duì)銀行卡操作實(shí)現(xiàn)類進(jìn)行增強(qiáng),每個(gè)方法都添加發(fā)送短信業(yè)務(wù),真正業(yè)務(wù)還是在銀行卡操作實(shí)現(xiàn)類中在進(jìn)行。

靜態(tài)代理的缺點(diǎn)

我們發(fā)現(xiàn)靜態(tài)代碼其實(shí)很麻煩,有點(diǎn)脫褲子放屁的意思.

靜態(tài)代理的缺點(diǎn):

1.要為每一個(gè)目標(biāo)類都要編寫相應(yīng)的代理類,會(huì)有很多代理類。

2.接口改了,目標(biāo)類和代理類都要跟著改。

二、動(dòng)態(tài)代理

我們只想寫增強(qiáng)的代碼,不需要寫代理類,增強(qiáng)代碼還可以復(fù)用到不同的目標(biāo)類。這時(shí)動(dòng)態(tài)代理橫空出世了。

動(dòng)態(tài)代理實(shí)現(xiàn)

1、獲取代理類方式一

1.JDK提供了 java.lang.reflect.Proxy類有一個(gè)getProxyClass(ClassLoader, interfaces)靜態(tài)方法,傳入類加載器,和接口,就可以得到代理類的Class對(duì)象.

2.得到了代理類的class對(duì)象,通過代理類的class對(duì)象得到構(gòu)造器,java.lang.reflect.InvocationHandler類中,每一個(gè)動(dòng)態(tài)代理類都要實(shí)現(xiàn)InvocationHandler接口,動(dòng)態(tài)代理對(duì)象調(diào)用一個(gè)方法時(shí),就會(huì)轉(zhuǎn)到實(shí)現(xiàn)InvocationHandler接口類的invoke方法.

3.得到代理類,實(shí)行調(diào)用.

public class ProxyTest {

    public static void main(String[] args) throws Exception {
        //目標(biāo)對(duì)象
        IBankCardService bankCard=new BankCardServiceImpl();
        //獲取代理對(duì)象
        IBankCardService proxyBank = (IBankCardService) getProxy(bankCard);
        //調(diào)用方法
        proxyBank.getMoney("9527");
    }
    
    /**
     * 獲取代理類
     * @param target 目標(biāo)類
     * @return
     * @throws SecurityException 
     * @throws NoSuchMethodException 
     */
    private static Object getProxy(Object target) throws Exception {
        //得到代理類大class
        Class proxyClass = Proxy.getProxyClass(target.getClass().getClassLoader(),     target.getClass().getInterfaces());
        //創(chuàng)建代理類的構(gòu)造函數(shù),構(gòu)造函數(shù)的方法必須傳入InvocationHandler接口的實(shí)現(xiàn)類
        Constructor constructor=proxyClass.getConstructor(InvocationHandler.class);
        //獲取代理類
        Object proxy =constructor.newInstance(new InvocationHandler() {
            
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //調(diào)用目標(biāo)文件的方法
                Object resulet = method.invoke(target,args);
                //增強(qiáng)方法
                System.out.println("向客戶發(fā)送短信");
                return resulet;
            }
            
        });
        return proxy;
    }
}

打印結(jié)果:
    查詢銀行卡賬號(hào)為:9527的賬戶 的余額
    向客戶發(fā)送短信

2、獲取代理類方式二

實(shí)際變成中不會(huì)使用getProxyClass(),因?yàn)镴DK的Proxy類提供了更好用的方法newProxyInstance(ClassLoader loader, Class[] interfaces,InvocationHandler h),直接傳入InvocationHandler 實(shí)現(xiàn)類就可以的到代理類.

1.代理類的調(diào)用處理程序?qū)崿F(xiàn)

/**
 * 發(fā)送短信調(diào)用類
 * @author yizl
 *
 */
public class SendMessageInvocation implements InvocationHandler {
    /**
     * 目標(biāo)類    
     */
    private Object obj;
    
    /**
     * 通過構(gòu)造方法傳參
     * @param obj
     */
    public SendMessageInvocation(Object obj) {
        this.obj=obj;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //調(diào)用目標(biāo)文件的方法
        Object resulet = method.invoke(obj,args);
        //增強(qiáng)方法
        System.out.println("向客戶發(fā)送短信");
        return resulet;

    }
}

2.獲取代理類,調(diào)用取錢方法

public class ProxyTest {
    public static void main(String[] args) throws Exception {
        // 獲取銀行卡操作實(shí)現(xiàn)類
        IBankCardService bankCard = new BankCardServiceImpl();
        // 獲取銀行卡操作類的代理類
        IBankCardService proxyBank = (IBankCardService)Proxy.newProxyInstance(bankCard.getClass().getClassLoader(),
        bankCard.getClass().getInterfaces(),new SendMessageInvocation(bankCard));
        proxyBank.outMoney("9527");
    }
}

打印結(jié)果:
    向銀行卡賬號(hào)為:9527的賬戶取錢
    向客戶發(fā)送短信

用JDK提供的代理類,很完美的解決了,不寫代理類,直接寫增強(qiáng)方法,直接就獲取到目標(biāo)的代理類。

三、動(dòng)態(tài)代理的應(yīng)用

設(shè)計(jì)模式中有一個(gè)設(shè)計(jì)原則是開閉原則:軟件中對(duì)于擴(kuò)展是開放的,對(duì)于修改是封閉的。再不改變?cè)创a的情況下,拓展它的行為。

工作中接收了很多以前的代碼,里面的邏輯讓人摸不透,就可以使用代理類進(jìn)行增強(qiáng)。

Spring的AOP就是Java的動(dòng)態(tài)代理來實(shí)現(xiàn)的切面編程。

RPC框架,框架本身不知道要調(diào)用哪些接口,哪些方法。這是框架可以一個(gè)創(chuàng)建代理類給客戶端使用。

實(shí)際開發(fā)中的,通用異常處理,通用日志處理,事物處理都可以用到動(dòng)態(tài)代理。

四、總結(jié)

優(yōu)點(diǎn):

動(dòng)態(tài)代理類簡(jiǎn)化了代碼編程工作,提高了軟件的可擴(kuò)展性。

缺點(diǎn):

JDK動(dòng)態(tài)代理只能代理有接口的實(shí)現(xiàn)類,沒有接口的類就不能用JDK的動(dòng)態(tài)代理。(Cglib動(dòng)態(tài)代理可以對(duì)沒有接口的類實(shí)現(xiàn)代理)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/77763.html

相關(guān)文章

  • Java中動(dòng)態(tài)代理

    摘要:要明白,動(dòng)態(tài)代理類的存在意義是為了攔截方法并修改邏輯而動(dòng)態(tài)代理的局限性之一就是只能攔截接口所聲明的方法。因?yàn)閯?dòng)態(tài)代理類是繼承自業(yè)務(wù)類,所以該類和方法不能聲明成無法繼承或重寫。者最終都是生成了一個(gè)新的動(dòng)態(tài)代理類對(duì)象。 動(dòng)態(tài)代理 1、先談靜態(tài)代理 對(duì)于靜態(tài)代理,我們已經(jīng)很熟悉了。我們擁有一個(gè)抽象類,真實(shí)類繼承自抽象類并重寫其業(yè)務(wù)方法,代理類持有真實(shí)類的對(duì)象實(shí)例,在重寫業(yè)務(wù)方法中通過調(diào)用真實(shí)...

    CastlePeaK 評(píng)論0 收藏0
  • Java設(shè)計(jì)模式綜合運(yùn)用(動(dòng)態(tài)代理+Spring AOP)

    摘要:動(dòng)態(tài)代理的核心是接口和類。以上結(jié)果說明它生成的代理類為,說明是代理。測(cè)試前提實(shí)現(xiàn)接口測(cè)試類使用接口方式注入代理方式必須以接口方式注入測(cè)試配置為,運(yùn)行結(jié)果如下實(shí)際校驗(yàn)邏輯。。。。 本文也同步發(fā)布至簡(jiǎn)書,地址:https://www.jianshu.com/p/f70... AOP設(shè)計(jì)模式通常運(yùn)用在日志,校驗(yàn)等業(yè)務(wù)場(chǎng)景,本文將簡(jiǎn)單介紹基于Spring的AOP代理模式的運(yùn)用。 1. 代理模...

    王晗 評(píng)論0 收藏0
  • Java動(dòng)態(tài)代理 jdk和cglib實(shí)現(xiàn)比較

    摘要:與靜態(tài)代理對(duì)比,動(dòng)態(tài)代理是在動(dòng)態(tài)生成代理類,由代理類完成對(duì)具體方法的封裝,實(shí)現(xiàn)的功能。本文將分析中兩種動(dòng)態(tài)代理的實(shí)現(xiàn)方式,和,比較它們的異同。那如何動(dòng)態(tài)編譯呢你可以使用,這是一個(gè)封裝了的庫,幫助你方便地實(shí)現(xiàn)動(dòng)態(tài)編譯源代碼。 發(fā)現(xiàn)Java面試很喜歡問Spring AOP怎么實(shí)現(xiàn)的之類的問題,所以寫一篇文章來整理一下。關(guān)于AOP和代理模式的概念這里并不做贅述,而是直奔主題,即AOP的實(shí)現(xiàn)方...

    h9911 評(píng)論0 收藏0
  • 吃透動(dòng)態(tài)代理,解密spring AOP源碼(四)

    摘要:值得一提的是由于采用動(dòng)態(tài)創(chuàng)建子類的方式生成代理對(duì)象,所以不能對(duì)目標(biāo)類中的方法進(jìn)行代理。動(dòng)態(tài)代理中生成的代理類是子類,調(diào)試的時(shí)候可以看到,打開源碼可看到實(shí)現(xiàn)了和也就實(shí)現(xiàn)方法。 前面講到了動(dòng)態(tài)代理的底層原理,接下來我們來看一下aop的動(dòng)態(tài)代理.Spring AOP使用了兩種代理機(jī)制:一種是基于JDK的動(dòng)態(tài)代理,一種是基于CGLib的動(dòng)態(tài)代理. ①JDK動(dòng)態(tài)代理:使用JDK創(chuàng)建代理有一個(gè)限制...

    Codeing_ls 評(píng)論0 收藏0
  • JDK動(dòng)態(tài)代理

    摘要:動(dòng)態(tài)代理是包提供的方式,它必須借助一個(gè)接口才能產(chǎn)生代理對(duì)象,所以要預(yù)先定義接口。第步,建立代理對(duì)象和真實(shí)對(duì)象的關(guān)系。第個(gè)是把生成的動(dòng)態(tài)代理對(duì)象下掛在哪些接口下,這個(gè)寫法就是放在實(shí)現(xiàn)的接口下。 JDK動(dòng)態(tài)代理是java.lang.reflect.*包提供的方式,它必須借助一個(gè)接口才能產(chǎn)生代理對(duì)象,所以要預(yù)先定義接口。 1. 接口 public interface Hello { ...

    qujian 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<