1. 程式人生 > >Java動態代理簡單例項:老闆與祕書

Java動態代理簡單例項:老闆與祕書

Java動態代理是Java中比較晦澀難懂的一個部分,雖然看了一些別人的部落格之後覺得自己大體明白了,但是事非經過不知難,自己寫的時候卻產生了諸多疑問。

本文用盡可能簡單的例子來說明Java動態代理的機制。

例子共四個部分:

1. ReadFile介面(批改檔案)

2. Boss類,委託類,能夠批改檔案

3. Secretary類,沒有實現ReadFile介面,用Secretary可建立代理類,“代理”Boss批改檔案(創建出來的代理類物件就是main函式中的secretary1)

4. Main類

1. ReadFile介面

public interface ReadFile {
    public void read();
}

2. Boss類,實現了ReadFile介面,可以批改檔案

public class Boss implements ReadFile {

    @Override
    public void read() {
        System.out.println("I'm reading files.");
    }

}

3. Secretary類,不是代理類,但利用這個類能創建出代理類

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

public class Secretary implements InvocationHandler {

    private Object object;
    
    public Secretary(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("I'm secretary.");
        Object result = method.invoke(object, args);

        return result;
    }

}

Secretary類中有一個變數object用來存boss物件,因為接下來Secretary要代理Boss做的事,因此先要把boss物件先儲存起來。

Secretary類如果想代理Boss做的事,即呼叫Boss類的方法,必須實現InvocationHandler,過載invoke方法,然後在invoke函式中呼叫Boss類的方法。

我們看到invoke函式中有一句method.invoke(object, args),代理類就是用這種方式呼叫委託類的方法。

4. Main類

import java.lang.reflect.Proxy;

public class Main {

    public static void main(String[] args) {
        ReadFile boss = new Boss();

        InvocationHandler handler = new Secretary(boss);

        ReadFile secretary = (ReadFile) Proxy.newProxyInstance(
                boss.getClass().getClassLoader(),
                boss.getClass().getInterfaces(),
                handler);
        
        secretary.read();
    }
}
整個函式的執行流程如下:

先是建立了一個boss物件,

然後建立一個handler物件,

然後利用handler構造出一個能呼叫boss方法的物件secretary,這個secretary就是代理類物件

執行最後一句時,代理類的public Object invoke(...)方法被呼叫,代理類在此處呼叫委託類的方法,method.invoke()先列印I'm secretary,再呼叫boss物件的方法read()。


secretary每呼叫一次read()時都會執行public Object invoke(...),顯而易見傳入的第二個引數method即read(),第三個引數args即傳入read()的引數(這裡沒有)。

實現了InvocationHandler的Secretary類並不能直接呼叫委託類的方法,handler物件只是一個handler,只有當handler物件用newProxyInstance方法包裹成secretary物件後,才具有呼叫boss方法的能力。

既然說secretary是由handler包裹而成的,那secretary是什麼型別的呢?

        System.out.println(secretary.getClass().getName());

型別是$Proxy0
如果文章中存在問題請及時指正。