動(dòng)態(tài)代理詳解

動(dòng)態(tài)代理的作用
通過(guò)反射調(diào)用代理對(duì)象,讓其幫我們實(shí)現(xiàn)一些非常頻繁的操作,如:權(quán)限校驗(yàn)和日志記錄
代理的實(shí)現(xiàn)原理:在Java中java.lang.reflect包下提供了一個(gè)Proxy類和一個(gè)InvocationHandler接口通過(guò)使用這個(gè)類和接口就可以生成動(dòng)態(tài)代理對(duì)象。這里只能針對(duì)接口實(shí)現(xiàn)代理,后期cglib可以實(shí)現(xiàn)類的代理
代理的實(shí)現(xiàn)過(guò)程:既然是代理,顧名思義,就是代替某個(gè)類或接口去實(shí)現(xiàn)某個(gè)功能,也就是說(shuō),我代理了你,我就具備了你的功能。怎么才能具有其他類或接口的功能呢:要么是繼承自類,要么是實(shí)現(xiàn)接口。而我們已經(jīng)知道,此處只能代理接口。所以在造該代理對(duì)象時(shí),肯定是讓其實(shí)現(xiàn)了被代理的接口。而實(shí)現(xiàn)了接口還只是第一步,我還要提供一些特有的功能所以再創(chuàng)建完動(dòng)態(tài)代理對(duì)象以后至少要實(shí)現(xiàn)這兩個(gè)目的:實(shí)現(xiàn)被代理的功能、并提供特殊功能。
具體步驟:首先由Proxy類的靜態(tài)方法newProxyInstance創(chuàng)建動(dòng)態(tài)代理對(duì)象

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)

而要?jiǎng)?chuàng)建該對(duì)象,需要3個(gè)參數(shù)ClassLoader loader:定義了由哪個(gè)ClassLoader對(duì)象來(lái)對(duì)生成的代理對(duì)象進(jìn)行加載Class<?>[] interfaces:表示的是我將要給我需要代理的對(duì)象提供一組什么接口InvocationHandler h:既然一個(gè)指明了加載器,一個(gè)指明了接口,那么這個(gè)就是具體實(shí)現(xiàn)功能的方法了。InvocationHandler對(duì)象,表示的是當(dāng)我這個(gè)動(dòng)態(tài)代理對(duì)象在調(diào)用方法的時(shí)候,會(huì)關(guān)聯(lián)到哪一個(gè)InvocationHandler對(duì)象上每一個(gè)動(dòng)態(tài)代理類都必須要實(shí)現(xiàn)InvocationHandler這個(gè)接口,當(dāng)我們通過(guò)代理對(duì)象調(diào)用一個(gè)方法的時(shí)候,這個(gè)方法的調(diào)用就會(huì)被轉(zhuǎn)發(fā)為由InvocationHandler這個(gè)接口的invoke 方法來(lái)進(jìn)行調(diào)用

public Object invoke(Object proxy, Method method, Object[] args)InvocationHandler

接口中invoke方法的三個(gè)參數(shù):proxy:代表動(dòng)態(tài)代理對(duì)象method:代表正在執(zhí)行的方法args:代表調(diào)用目標(biāo)方法時(shí)傳入的實(shí)參由此可知,實(shí)際在實(shí)現(xiàn)InvocationHandler接口重寫invoke方法時(shí),所需要的三個(gè)參數(shù)都不要我們給出

public interface StudentDao {  
  
    public abstract void login();  
      
    public abstract void regist();  
}  
public class StudentDaoImpl implements StudentDao {  
  
    @Override  
    public void login() {  
        System.out.println("登錄功能");  
    }  
  
    @Override  
    public void regist() {  
        System.out.println("注冊(cè)功能");  
    }  
  
}  
/* 
 * 由于該對(duì)象要重寫的方法中會(huì)調(diào)用代理對(duì)象的方法,所以需要把被代理的目標(biāo)對(duì)象以參數(shù)的方法傳入 
 * 然后使用反射調(diào)用目標(biāo)對(duì)象的方法 
 */  
public class MyInvocationHandler implements InvocationHandler {  
  
    private Object target;  //目標(biāo)對(duì)象  
    public MyInvocationHandler(Object target){  
        this.target = target;  
    }  
      
    @Override  
    public Object invoke(Object proxy, Method method, Object[] args)  
            throws Throwable {  
        //代理要提供的特殊功能  
        System.out.println("權(quán)限校驗(yàn)");  
          
        //通過(guò)反射執(zhí)行目標(biāo)對(duì)象的方法  
        method.invoke(target, args);  
          
        //代理要提供的特殊功能  
        System.out.println("日志記錄");  
        return null;//如果底層方法返回類型為 void,則該調(diào)用返回 null  
    }  
}  

創(chuàng)建動(dòng)態(tài)代理對(duì)象并實(shí)現(xiàn)功能

import java.lang.reflect.Proxy;  
  
/* 
 分析: 
 登錄注冊(cè)屬于用戶的擴(kuò)展功能,用接口實(shí)現(xiàn) 
 然后重寫抽象方法,實(shí)現(xiàn)接口 
 創(chuàng)建實(shí)現(xiàn)InvocationHandler接口的對(duì)象作為Proxy的參數(shù)使用(其實(shí),底層方法的調(diào)用即特殊功能的實(shí)現(xiàn)都是通過(guò)該對(duì)象實(shí)現(xiàn)的) 
 由Proxy的靜態(tài)方法創(chuàng)建動(dòng)態(tài)代理對(duì)象,由于返回值是Object所以需要向下轉(zhuǎn)型 
 */  
public class ProxyDemo {  
    public static void main(String[] args) {  
        // 創(chuàng)建被代理對(duì)象  
        StudentDao st = new StudentDaoImpl();  
        // 創(chuàng)建實(shí)現(xiàn)InvocationHandler接口的對(duì)象  
        MyInvocationHandler mi = new MyInvocationHandler(st);  
        // 創(chuàng)建動(dòng)態(tài)代理對(duì)象  
        StudentDao proxy = (StudentDao) Proxy.newProxyInstance(st.getClass().getClassLoader(), st.getClass().getInterfaces(), mi);  
        //用動(dòng)態(tài)代理對(duì)象調(diào)用方法  
        proxy.login();  
        proxy.regist();  
    }  
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容