美文网首页
Proxy源码学习

Proxy源码学习

作者: tiancijiaren | 来源:发表于2017-07-12 09:48 被阅读0次

    动态代理使用不在累述。InvocationHandler.invoke的第一个参数proxy值是newProxyInstance返回的动态代理类的实例,不是被代理的实例。
    动态代理类Proxy是结合java底层实现的,通过纯粹的java代码实现比较困难。
    需要java动态生成类的支持。

    要创建一个可以代理任何接口的类:

    1.必须要知道要被代理的接口列表;
    2.要有一个可以加载这个代理类的ClassLoader;
    3.为了能够在调用被代理实例接口时能够动态的添加需要的处理,需要一个接口回调,并在回调中采用反射的形式调用实际的实例方法。

    实现过程:以下Proxy是实现动态代理的过程

    public interface Subject{
    public void rent();
    public void hello(String str);
    }
    public class RealSubject implements Subject{
    @Override
    public void rent() {
    System.out.println("I want to rent my house");
    }
    @Override
    public void hello(String str) {
    System.out.println("hello: " + str);
    }
    }
    public class DynamicProxyHandler implements InvocationHandler {
    // 被代理对象
    private Object subject;
    public DynamicProxy(Object subject) {
    this.subject = subject;
    }
    @Override
    public Object invoke(Object object, Method method, Object[] args) throws Throwable {
    // 在代理真实对象前我们可以添加一些自己的操作
    System.out.println("Method:" + method);
    // 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
    method.invoke(subject, args);
    // 在代理真实对象后我们也可以添加一些自己的操作
    System.out.println("after rent house");
    return null;
    }
    }
    public static void main(String[] args) {
    Subject realSubject = new RealSubject();
    InvocationHandler handler = new DynamicProxyHandler(realSubject);
    Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
    .getClass().getInterfaces(), handler);
    System.out.println(subject.getClass().getName());
    subject.rent();
    subject.hello("world");
    }
    subject.getClass().getName()打印的值是:$Proxy0


    image.png

    猜测大概的$Proxy0类如下(可以通过反射查看其中的一部分实际内容):

    // 类的包名应该是和Proxy在同一个包下
    public class Proxy0 implements Subject {
        private InvocationHandler handler;
        public Proxy0(InvocationHandler handler) {
            this.handler = handler;
        }
    
        public void rent() {
            Thread.currentThread().getStackTrace()[2].getMethodName();
            // 通过反射获取当前函数名称和参数列表,传给invoke
            Proxy.invoke(this, method, args);
        }
    
        public void hello(String str) {
            Proxy.invoke(this, method, args);
        }
    }
    

    InvocationHandler的实现可以多种多样,根据不同需求进行不同实现。

    相关文章

      网友评论

          本文标题:Proxy源码学习

          本文链接:https://www.haomeiwen.com/subject/mqjdxxtx.html