java核心学习(四十) 使用反射生成JDK动态代理

  java.lang.reflect包下提供了一个Proxy类和InvocationHandler接口,用于生成动态代理类和动态代理对象。

一、使用Proxy、InvocationHandler创建动态代理

  这里要注意,在java.net包下也有一个Proxy类,不过这个类是用于设置代理服务器的,莫混淆。。

  Proxy提供了如下两个方法创建动态代理类和动态代理实例:

    

  实际上即使采用第一种方法创建动态代理类,如果程序需要通过该代理类来创建对象,依然需要传入一个InvocationHandler对象,也就是说,系统生成的每个代理对象都有一个与之关联的InvocationHandler对象。

public class ProxyTest {
    public static void main(String[] args){
        MyInvocationHandler invocationHandler = new MyInvocationHandler();
        invocationHandler.setTarget(new Hero());
        Person hero= (Person) Proxy.newProxyInstance(Hero.class.getClassLoader(),Hero.class.getInterfaces(),invocationHandler);
//        hero.fight();
//        hero.laugh();
        hero.sayHello("Tom");
        hero.work();
    }
}
interface Person{
    void work();
    void sayHello(String name);
}
interface FightAble{
    void fight();
}
class Hero implements Person,FightAble{
    @Override
    public void fight() {
        System.out.println("hero fight");
    }

    @Override
    public void work() {
        System.out.println("hero work");
    }

    @Override
    public void sayHello(String name) {
        System.out.println("hello "+name);
    }
    public void laugh(){
        System.out.println("hero laugh");
    }
}
class MyInvocationHandler implements InvocationHandler{
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("-------正在执行的方法:"+method);
        if(args != null){
            System.out.println("下面是执行该方法传入的实参:");
            for (Object val : args){
                System.out.println(val);
            }
        }

        else {
            System.out.println("调用的方法没有实参");
            method.invoke(target);
        }
        return null;
    }
}

  注意,java动态代理产生的对象一定要用接口引用指向之,这是由于java的动态代理实际上时使用传入的接口类型创建了新的类,所以在上面代码中不可以用Hero类型指向创建的对象,只能由Person或FightAble类型指向之。看源码就可以发现这一点。

二、AOP代理

  AOP(面向切面编程),的一种实现方式就是使用java动态代理。

  在上面的代码中实际上已经实现了AOP,对所有代理对象的无实参方法,在执行方法body之前都先执行System.out.println("调用的方法没有实参");只不过这些代码写在了InvocationHandler中,而像Spring之类的框架会把这一部分代码用设计模式解耦出来,但本质上还是这样子的原理。

posted @ 2017-10-31 23:23  The_shy  阅读(320)  评论(0编辑  收藏  举报