zoukankan      html  css  js  c++  java
  • jdk动态代理实现原理总结

    运行时创建一个代理对象的步骤为

    1. 生成代理类的字节码
    2. 加载字节码,创建代理对象

    首先,代理对象的目的是在被调用方法的时候既能实现被代理对象的方法,又能够增加自己想要执行的方法,自然要获得被代理对象

    代理类需要实现被代理对象的类的接口,因此生成的代理对象可以调用被代理对象所执行的方法。因此,创建代理类需要获得被代理对象的类的接口(反射获得)

    代理类实现的接口方法由用户自定义放到一个类方法里,因此代理类需要拿到这个用户自定义的类(构造方法或者set方法)

    既然要加载字节码,肯定要获得classLoader,可以由被代理对象从反射获得。

     

    因此生成代理对象的方法为

    //target为代理对象

    public <T> T getProxy() {
            return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),//类加载器,用于加载生成的代理类字节码
        target.getClass().getInterfaces(), //代理类需要实现被代理对象的类的接口
         this//用户自定义的代理方法的实现
    ); }
    以上为下面完整实现代码的截取 完整动态代理实现例子如下:
    摘自

    JDK动态代理实现原理

    package com.lnjecit.proxy;
    
    /**
     * Subject
     * 抽象主题接口
     * @author
     * @create 2018-03-29 14:16
     **/
    public interface Subject {
    
        void doSomething();
    }
    复制代码

     然后为接口RealSubject新建一个实现类RealSubject

    复制代码
    /**
     * RealSubject
     * 真实主题类
     * @author
     * @create 2018-03-29 14:21
     **/
    public class RealSubject implements Subject {
        @Override
        public void doSomething() {
            System.out.println("RealSubject do something");
        }
    }
    复制代码

     接着创建一个代理类JDKDynamicProxy实现java.lang.reflect.InvocationHandler接口,重写invoke方法

    复制代码
    package com.lnjecit.proxy.dynamic.jdk;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    /**
     * JDKDynamicProxy
     * jdkd动态代理
     *
     * @author
     * @create 2018-03-29 16:17
     **/
    public class JDKDynamicProxy implements InvocationHandler {
    
        private Object target;
    
        public JDKDynamicProxy(Object target) {
            this.target = target;
        }
    
        /**
         * 获取被代理接口实例对象
         * @param <T>
         * @return
         */
        public <T> T getProxy() {
            return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("Do something before");
            Object result = method.invoke(target, args);
            System.out.println("Do something after");
            return result;
        }
    }
    复制代码

    新建测试类Client测试结果

    复制代码
    package com.lnjecit.proxy;
    
    import com.lnjecit.proxy.dynamic.jdk.JDKDynamicProxy;
    
    /**
     * Client
     * client测试代码
     *
     * @author
     * @create 2018-03-29 14:26
     **/
    public class Client {
        public static void main(String[] args) {
            // 保存生成的代理类的字节码文件
            System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
    
            // jdk动态代理测试
            Subject subject = new JDKDynamicProxy(new RealSubject()).getProxy();
            subject.doSomething();
        }
    }
    复制代码

    输出结果:

    Do something before
    RealSubject do something
    Do something after

  • 相关阅读:
    一致性哈希算法 CARP 原理解析, 附 Golang 实现
    springSecurity自定义认证配置
    jeecms常用的标签
    AngularJs分层结构小demo
    springSecurity入门小demo--配置文件xml的方式
    angularJs实现下拉框多选
    angularJs实现动态增加输入框
    js判断当前页面是顶级窗口
    angularJs的继承
    在angularJs实现批量删除
  • 原文地址:https://www.cnblogs.com/cai-cai777/p/11210721.html
Copyright © 2011-2022 走看看