歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Java 動態代理介紹及用法

Java 動態代理介紹及用法

日期:2017/3/1 9:08:17   编辑:Linux編程

一,靜態代理模式的特點

在之前的文章中 Java代理模式 已經介紹裡Java裡的(靜態)代理模式 http://www.linuxidc.com/Linux/2016-12/138191.htm

下面是上文靜態代理類的例子:

public class ProxyBear implements Hitable<Dog>{  
    private Hitable<Dog> f = null;  
    public ProxyBear(){  
        if (null == f){  
            f = new Fox();  
        }  
    }  

    @Override  
    public void hit(Dog g){  
        if (null != f){  
            System.out.println("Bear hit InterDogChicken!");  
            f.hit(g);  
            System.out.println("Bear bite InterDogChicken!");  
        }  
    }  

從代碼可以看出, 上面代理類可以增強被代理的對象的某個方法。
但是被代理對象的類型Hitable是指定1個接口(或抽象類)

也就是講上靜態代理類只適用於某一種指定的接口實現類, 如果某個對象沒有實現揍狗接口, 而是其他另1個接口, 那麼就必須新建1個代理類的。即使新代理類也是實現同樣的功能

二. 動態代理的1個需求

就用會上文的例子

我們宜家有兩個接口。毆打和調戲接口..

毆打接口 Hitable

public interface Hitable<T> {
    public void hit(T o);
}

調戲接口 Molestable

public interface Molestable<T> {
    public void molest(T o);
}

其中狐狸類實現了毆打狗接口

public class Fox implements Hitable<Dog> {
    @Override
    public void hit(Dog g){
        this.sap(g);
        this.uppercut(g);
    }

    //悶棍
    private void sap(Dog g){
        System.out.println("give " + g.getName() + " a Sap!");
    }

    //上勾拳
    private void uppercut(Dog g){
        System.out.println("give " + g.getName() + " a Uppercute!");
    }
}

狼類實現調戲狗接口

public class Wolf implements Molestable<Dog> {
    @Override
    public void molest(Dog o) {
        System.out.println("wolf laugh at the dog!");
        System.out.println("wolf ruffle the dog!");
    }
}

這個是萬惡的狗類

public class Dog {
    private String name;
    public Dog(String name){
        this.setName(name);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Dog [name=" + name + "]";
    }
}

問題來了, 依家狗太惡, 狼和狐狸都要找頭熊(代理)看著才敢去惹狗

如果用靜態代理, 就如本文一開始的那個代理類, 則只能單獨為狐狸or 狼代理, 這個需求需要兩個代理類, 因為狗和狐狸實現的是兩個不同的接口

如下圖

那麼有沒有一種代理類, 可以同時代理多個接口的實現類呢,java 裡動態代理就利用了反射實現了這個功能。

三,動態代理的例子

我們利用動態代理類重新寫了1個熊類出來:

public class dynamicProxyBear implements InvocationHandler {
    //delegate means proxy
    //the object which will be delegated
    private Object delegate;

    public Object bind(Object delegate){
        this.delegate = delegate;

        /**
         * This method newProxyInstance return ***one of the interfaces*** of delegate object(properties object of this class)
         * 
         * @param 
         *      1.ClassLoader loader -> usually use delegate object's class loader
         *      2.Class<?>[] interfaces -> collection of the interface which delegate object has implemented
         *      3.InvocationHandler h -> this
         * @return
         */
        return Proxy.newProxyInstance(delegate.getClass().getClassLoader(), 
                                      delegate.getClass().getInterfaces(), this);

    }

    /**
     * This method will replace all the method owned by delegate object.
     * @param proxy -> the delegate object, never use it's method directly, otherwise will lead to Dead loop
     * @param method -> the method (once execute will fall into this invoke method) object of delegate object 
     * @param args  -> parameters of the mothod.
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        Object result;

        if (args.length < 1){
            return method.invoke(this.delegate,args);
        }

        //bear watching
        System.out.println("bear is watching " + args[0].toString());
        result = method.invoke(this.delegate,args);
        System.out.println("bear leaved " + args[0].toString());
        return result;
    }
}

更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2016-12/138192p2.htm

Copyright © Linux教程網 All Rights Reserved