反射實現動態代理原理

我記得在spring中有用到在xml文件中配置一些類和方法,而後在實際調用這些類的方法的時候依照配置文件的信息,在運行這些方法的同時(前、後)。同時調用一些已經配置好的方法(好比說日誌記錄)。這就是動態代理的一些體現。java

靜態代理和動態代理的區別:我我的以爲,靜態代理主要經過在代理對象中直接實例出一個被代理的對象,在編譯執行代碼以前已經明確地寫出代理對象的各類方法。而動態代理的代理對象並不是顯式的新建一個被代理的對象的方法,而是經過反射原理在執行代理對象的方法的時候同時執行被代理對象的方法。spring

下面咱們就新建一個場景,經過反射實現動態代理。ide

唉~ 實在想不出什麼高深的場景實現,就以搭火車回家這個行爲做爲模擬場景吧。呃。。想了一下,好像坐火車不適合作代理。。。就託運個貨物吧。函數

package demo.taketrain;

/**
 * Created by li on 2016/12/21.
 */
public class Cargo implements Ridable, ICargo {
    private String name;
    private Ridable ridable;

    public Cargo(String name, Ridable ridable) {
        this.name = name;
        this.ridable = ridable;
    }

    @Override
    public void rideTrain() {
        ridable.rideTrain();
    }
}
package demo.taketrain;

/**
 * Created by 爹 on 2016/12/21.
 */
public interface ICargo {
    void rideTrain();
}
package demo.taketrain;

/**
 * Created by li  on 2016/12/21.
 */
public interface Ridable {
    void rideTrain();
}
package demo.taketrain;


import java.util.Date;

/**
 * Created by 爹 on 2016/12/21.
 */
public class RideTrainBehavior implements Ridable {
    private String startPoint;
    private String destination;

    /**
     * 構造函數,每一次乘車行爲都須要有始發地和目的地、
     */

    public RideTrainBehavior(String startPoint, String destination) {
        this.startPoint = startPoint;
        this.destination = destination;
    }

    @Override
    public void rideTrain() {
        System.out.print("運貨,乘車時間:");
        System.out.println(new Date().toString());
        System.out.println("始發地:" + startPoint);
        System.out.println("目的地:" + destination);
    }
}
package demo.taketrain;

/**
 * Created by 爹 on 2016/12/21.
 */
public class TrainTransportation implements TransportationProxy {

    @Override
    public void transportCargo(Cargo cargo) {
        System.out.println("運輸以前要安檢");
        cargo.rideTrain();
        System.out.println("運輸以後要收錢");
    }
}
package demo.taketrain;

/**
 * Created by li on 2016/12/21.
 */
public interface TransportationProxy {
    void transportCargo(Cargo cargo);
}

從這看出要動態的代理運貨的任務,仍是須要得到實體對象——貨物。經過一我的(main方法)將貨物對象(名稱,開始地,目的地)給代理運輸的公司。就可實現代理運輸,各類不一樣貨物均可運輸。(這就是動態代理了?)沒用用到反射。this

不行,必須用反射實現一下下。應該改變一下思路。運輸部門得到這個物品,知道這個物品有個運輸的方法。可經過xml配置。 而後代理類在得到物品和方法以後添加本身須要作的一些事情而後一塊兒處理。代理

我大概又看了下反射的用法。下面有一個簡單的實例。日誌

/**
 * Created by li on 2016/12/21.
 */
public class Person {
    public String name="ds";

    public String getName() {
        return name;
    }

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

    public void introduce() {
        System.out.println("My name is " + name);
    }
}
/**
 * Created by li on 2016/12/21.
 */
public class RefleckDemo {
    public static void main(String[] args) throws IllegalAccessException, InvocationTargetException {
        Class<Person> personClass = Person.class;
        personClass.getInterfaces();
        //參數

        java.lang.reflect.Field[] fields = personClass.getDeclaredFields();
        java.lang.reflect.Field field = fields[0];
        Person person = new Person();
        Object s = field.get(person);
        System.out.println(personClass);

        //方法
        Method[] methods = personClass.getDeclaredMethods();
        Method method = methods[0];
        Method method1 = methods[1];
        Method method2 = methods[2];
        method1.invoke(person, "dsadsadsa");
        Object o = method.invoke(person);
        System.out.println(methods);
    }
}

由上面能夠看出。無論是反射包中的Field,仍是Method。經過類反射出來的屬性,只能描述這個類中數據或方法的一些基本內容。假如經過放射調用方法,你首先必需要建立實體對象。由以上實例知道,當你得到了待運送的實例類貨物的時候,同時你在知道調用的名字的前提下你應該知道經過已知的方法名獲得Method對象,而後調用該對象的invoke()方法可得可動態的調用對象的方法,也可在該方法中加入一些其餘針對實體對象的方法一併處理。xml

相關文章
相關標籤/搜索