1. 程式人生 > 其它 >Proxy 實現動態代理

Proxy 實現動態代理

檔案結構:

  • Child.class [Interface]
  • ChildImpl.class
  • MyProxy.class [Test Class]

一、Child.class

package proxys;

public interface Child {
    void eat();
}

二、ChildImpl.class

package proxys;

public class ChildImpl implements Child {
    @Override
    public void eat() {
        System.out.println("Child eating...");
    }
}

三、MyProxy.class

package proxys;

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

/**
 * 基於介面的動態代理: Proxy, InvocationHandler
 */
public class MyProxy {

    /**
     * Test Method
     * @param args 引數列表
     */
    public static void main(String[] args) {
        // 未使用代理模式
        ChildImpl child = new ChildImpl();
        child.eat();

        // 使用動態代理增強日誌功能
        System.out.println();
        Child proxyObj = getProxyObj(child, Child.class);
        proxyObj.eat();
    }

    /**
     * 獲取代理物件
     * @param obj 被代理的物件
     * @param interfaceType 被代理方法所屬的介面型別
     * @return 代理物件
     */
    public static <I> I getProxyObj(Object obj, Class<I> interfaceType) {
        // 介面型別檢查, 因為 Proxy 是基於介面的動態代理
        Class<?>[] type = null;
        Class<?>[] interfaces = obj.getClass().getInterfaces();
        for (Class<?> anInterface : interfaces) {
            if (anInterface.equals(interfaceType)) {
                type = new Class[]{anInterface};
                break;
            }
        }
        if (null == type) {
            throw new ClassCastException("無法將物件 " + obj + " 代理為 " + interfaceType.getName());
        }

        Object o = Proxy.newProxyInstance(obj.getClass().getClassLoader(), type,
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // 增強呼叫前的功能
                        System.out.println("[" + method.getName() + "] Proxy begin...");
                        // 呼叫被代理物件的方法
                        Object ret = method.invoke(obj, args);
                        // 增強呼叫後的功能
                        System.out.println("[" + method.getName() + "] Proxy end...");
                        return ret;
                    }
        });

        return (I) o;
    }
}

執行結果:

Child eating...

[eat] Proxy begin...
Child eating...
[eat] Proxy end...