反射的应用之动态代理

动态代理的使用,反射是动态语言的关键

TestDynamicProxy

package com.aff.dynamic;

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

/*
 动态代理是指客户通过代理类来调用其它对象的方法,
 并且是在程序运行时根据需要动态创建目标类的代理对象。
 动态代理使用场合:
                            调试
                            远程方法调用
代理设计模式的原理: 
                   使用一个代理将对象包装起来, 然后用该代理对象取代原始对象. 
                   任何对原始对象的调用都要通过代理. 代理对象决定是否以及何时将方法调用转到原始对象上。
 */


//动态代理的使用,反射是动态语言的关键
interface Subject {
    void action();
}

// 被代理类
class RealSubject implements Subject {
    public void action() {
        System.out.println("我是被代理类,记得要执行");
    }
}

//代理类
class MyInvocationHandler implements InvocationHandler {
    Object obj;// 实现了接口的 被代理类的 对象的声明
    //                 ①给被代理类的对象实例化
    //                 ②返回一个代理类的对象

    public Object blind(Object obj) {
        this.obj = obj;
        // Proxy:代理类
        // Proxy.newProxyInstance :new一个代理类的实例,也要实现 对应被代理类的 实现接口里的抽象方法
        // obj.getClass().getClassLoader(): 和obj的类加载器是一样的,obj是和被代理类的对象类加载器相同的
        // obj.getClass().getInterfaces(); 被代理类实现的什么接口, 代理类(Proxy)也一样
        // this : 实现了InvocationHandler接口的类对象,也就是MyInvocationHandler
        // 这一步真正的返回一个代理类的对象
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
    }

    // 每当代理类的对象调用 被重写的action方法时,就会被转化为对如下invoke方法的调用
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)  throws Throwable {
        //returnVal  返回值相当于被代理类的抽象方法(action)的返回值
        Object returnVal = method.invoke(obj, args);//obj 被代理类的
        return returnVal;
    }
}

public class TestDynamicProxy {
    public static void main(String[] args) {
        //1.被代理类的对象
        RealSubject real= new RealSubject();
        //2.创建一个实现 InvocationHandler接口的类对象
        MyInvocationHandler handler = new MyInvocationHandler();
        //3.调用blind()方法,动态的返回一个同样实现了real所在类 实现的接口 的代理的对象
         Object obj = handler.blind(real);//real 是Subject类型,用Object来接收
         Subject sub = (Subject)obj;//得强转一下再调用action,此时的sub 就是代理类的对象、
         
         sub.action();//转到对 InvocationHandler接口的实现类(MyInvocationHandler)的invoke()方法的调用
    }
}

猜你喜欢

转载自www.cnblogs.com/afangfang/p/12625808.html