1. 程式人生 > >反射與動態代理

反射與動態代理

反射是動態語言的關鍵,動態代理正是通過反射實現

 

 

一.靜態代理:

   靜態代理是通過構建代理類物件,將被代理類物件以引數的形式傳遞給代理類物件,進而在代理類物件中呼叫被代理類的方法。

程式碼實現如下:

1.建立介面

2.定義被代理類實現介面

3.定義代理類,通過代理類的構造方法為其被代理類物件屬性賦值,代理類的productCloth()方法實際呼叫的是被代理類物件的方法

4.建立main方法測試

package D19;

/**
 * @Author: wj
 * @Date: 2018/12/1 16:19
 * @Version 1.0
 *
 * 靜態代理演示
 * 使用一個代理類將物件包裝起來,然後用該代理物件取代原始物件,任何對原始物件的呼叫
 * 都要通過代理,代理物件決定是否以及何時將方法呼叫轉到原始物件上
 */


/**
 *介面
 */
interface ClothFactory{
    public void productCloth();
}


/**
 *被代理類
 */
class NikeClothFactory implements ClothFactory{

    public void productCloth() {
        System.out.println("NIKE");
    }
}


/**
 * 代理類
 */
class ProxyFactory implements ClothFactory{
    ClothFactory cf ;

    /**建立代理類物件時,實際傳入的是被代理類物件
     * @param cf(多型)
     */
    public ProxyFactory(ClothFactory cf){
        this.cf=cf;
    }


    public void productCloth() {
        cf.productCloth();
    }
}


public class TestStaticAgent {
    public static void main(String[] args) {
        NikeClothFactory nikeClothFactory = new NikeClothFactory();  //建立被代理類物件
        //代理類物件
        ProxyFactory proxyFactory = new ProxyFactory(nikeClothFactory);  //建立代理類物件
        //雖然執行的是代理類的productCloth();但實際呼叫的是被代理類的productCloth()方法
        proxyFactory.productCloth();
    }
}

5.輸出:

 

二.動態代理

動態代理比靜態代理更加自如,不必考慮代理類接受物件的型別,具有更加自如地靈活性,實現了動態程式碼

步驟與靜態代理相同

1.定義介面

2.定義實現介面的被代理類

3.定義實現了InvocationHandler介面的代理類,定義blind方法接受被代理類物件(作用有兩個1.為屬性賦值,2返回實現了被代理類所實現介面的代理類物件),實現了invoke方法,該方法實際就是被帶了類的方法

程式碼如下:

package D19;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @Author: wj
 * @Date: 2018/12/2 13:38
 * @Version 1.0
 *
 * 動態代理的使用
 */



//介面
interface Subject{

    void action();
}


/**
 * 被代理類
 */
class RealSubject implements Subject{

    public void action() {
        System.out.println("被代理類執行");
    }
}


/**
 * 代理類
 */
class MyInvocationHandler implements InvocationHandler{
    Object object;//實現了介面的被代理類物件的宣告(RealSubject)


    // 1.給被代理類的物件例項話
    //2.返回一個代理類的物件
    public Object blind(Object obj){
        this.object = obj;

        //三個引數被代理類物件的classLoader,被代理類實現的介面,實現了InvocationHandler介面的類物件
        return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);
    }


    //當通過代理類的物件發起對被代理類方法的呼叫時,都會轉為對invoke方法的呼叫,進而實現動態效果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        //returnVal是被代理類方法的返回值
        Object returnVal =  method.invoke(object,args);


        System.out.println("invoke方法被呼叫");
        return returnVal;
    }
}


public class TestDynamicAgent {
    public static void main(String[] args) {
        //1.構造被代理類的物件
        RealSubject realSubject = new RealSubject();

        //2建立一個實現了InvocationHandle介面的物件
        MyInvocationHandler myInvocationHandler = new MyInvocationHandler();

        //3.通過myInvocationHandle的blind方法 ,返回實現了被代理類所實現的介面的代理類物件
        Object obj =  myInvocationHandler.blind(realSubject);
        Subject sub = (Subject) obj;//sub就是i代理類的物件

        sub.action();//轉到對代理類的inovke方法的呼叫





//        //測試動態代理
//        NikeClothFactory clothFactory = new NikeClothFactory();
//        Object demo = myInvocationHandler.blind(clothFactory);
//        ClothFactory clo = (ClothFactory) demo;
//        clo.productCloth();


    }
}

輸出:

 

在main方法中還寫了一個測試,具體的應用了動態代理。