教育行業(yè)A股IPO第一股(股票代碼 003032)

全國咨詢/投訴熱線:400-618-4000

Java培訓實戰(zhàn)教程之Java的動態(tài)代理

更新時間:2015年12月29日13時24分 來源:傳智播客Java培訓學院 瀏覽次數(shù):

     前面我們已經(jīng)介紹了代理的好處了,前面寫的是靜態(tài)代理,要手工創(chuàng)建代理類。下面,我們說說它的問題,我們發(fā)現(xiàn),代理類和老板類都實現(xiàn)了一個接口,如果業(yè)務(wù)繁多,這樣的接口會有很多,如果代理的功能是通用的,就需要對每個接口創(chuàng)建相應的代理類,這個叫類爆炸(類太多了),所以Java提供了動態(tài)代理,即程序運行時動態(tài)創(chuàng)建代理類的.class.
 
來看一下動態(tài)代理:
JDK動態(tài)代理中包含一個類和一個接口:
InvocationHandler接口: 代表代理對象關(guān)聯(lián)的處理代碼
public interface InvocationHandler {
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
}
參數(shù)說明:
Object proxy:指被代理的對象(老板)
Method method:要調(diào)用的方法
Object[] args:方法調(diào)用時所需要的參數(shù)
 
調(diào)用代理對象的所有方法都會被替換成執(zhí)行InvocationHandler的invoke()方法
Proxy類:
Proxy類是創(chuàng)建代理對象的工具類,此類提供了如下的操作方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,
InvocationHandler h) throws IllegalArgumentException
參數(shù)說明:
ClassLoader loader:類加載器
Class<?>[] interfaces:得到全部的接口
InvocationHandler h:得到InvocationHandler接口的子類實例 
 
與靜態(tài)代理類對照的是動態(tài)代理類,動態(tài)代理類的字節(jié)碼在程序運行時由Java反射機制動態(tài)生成,無需程序員手工編寫它的源代碼。動態(tài)代理類不僅簡化了編程工作,而且提高了軟件系統(tǒng)的可擴展性,因為Java 反射機制可以生成任意類型的動態(tài)代理類。java.lang.reflect 包中的Proxy類和InvocationHandler 接口提供了生成動態(tài)代理類的能力。
 
動態(tài)代理示例: 
 
//1.演出的接口
public interface Inter{ 
//演出
    public void show();

 
 
//2.某明星(被代理的類,可以理解為老板)
 
public class 明星A  implements Inter { //實現(xiàn)表演接口
 
    //明星表演 
    public void show() { 
        System.out.println("明星A賣力表演中。。。"); 
    } 
 
}  
 
/**
 * 3.JDK動態(tài)代理關(guān)聯(lián)的處理代碼  
 */ 
public class InvocationHandlerImpl  implements InvocationHandler { 
/*
這個target是經(jīng)紀人要代理的明星,是Object類型,如果經(jīng)紀人這個功能是通用的,可以適用于所有要被代理的類.而不用為每種類型的明星都創(chuàng)建一個代理類,這就是動態(tài)代理的好處,不像靜態(tài)代理那樣,要為很多老板類創(chuàng)建代理類
*/
private Object target;
 
 
    /**
     * 綁定一個明星并返回一個代理對象(一個經(jīng)紀人)
     * @param target
     * @return
     */ 
    public Object bind(Object target) { //傳入一個要被代理的具體的明星對象
        this.target = target;
        //返回代理對象(這個代理對象實現(xiàn)了和 target一樣的接口)
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), 
                target.getClass().getInterfaces(), this);
    } 
 
    @Override 
    /**
     * 調(diào)用代理對象的方法都會執(zhí)行invoke()方法
     */ 
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable  { 
       
        System.out.println("拍戲前簽合同");  //拍戲的前期工作
        Object result = method.invoke(target, args);  //中間讓明星去表演
        System.out.println("拍戲結(jié)束后的后期工作"); //拍戲后的后期工作
        return result; 
    } 
 

 
 
4.客戶端調(diào)用
 
public class TestProxy { 
 
public static void main(String[] args) { 
//創(chuàng)建關(guān)聯(lián)的處理代碼實現(xiàn)類
        InvocationHandlerImpl   handler = new InvocationHandlerImpl();
//返回代理對象(這個代理對象的.class是動態(tài)生成的)
        Inter proxy = (Inter) handler .bind(new 明星A());
//調(diào)用代理對象的show方法,實際執(zhí)行的是handler 的invoke()方法
        proxy .show();
    } 
 

 
    可能大家覺得這個動態(tài)代理也沒什么用?是的,在普通開發(fā)中,這個是很少用的,
但在搭建系統(tǒng)框架和底層開發(fā)中,是會用到的。
 
    JDK的動態(tài)代理依靠接口實現(xiàn),如果有些類并沒有實現(xiàn)接口,則不能使用JDK的動態(tài)代理,這就要使用cglib動態(tài)代理了。
 
 本文版權(quán)歸傳智播客Java培訓學院所有,歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明作者出處。謝謝!
作者:傳智播客Java培訓學院
首發(fā):http://xamj520.com/javaee 

0 分享到:
和我們在線交談!