反射实现动态代理原理

我记得在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

相关文章
相关标签/搜索