zoukankan      html  css  js  c++  java
  • 深挖JDK动态代理(一)

     最近在研究RPC框架,避免不了的就是在RPC调用中使用最多的则是动态代理的机制了,基于此,我们先来研究一下JDK动态代理

    我们先来尝试着编写一下JDK动态代理的代码

    1. 由于JDK动态代理是基于接口的,所以不免需要先编写一个接口,并声明一个getHello方法

    package cn.lonecloud.study.service;
    
    import cn.lonecloud.study.dto.HelloDto;
    
    /**
     * @author lonecloud
     * @version v1.0
     * @Package cn.lonecloud.study
     * @Description: TODO
     * @date 2018/6/8下午4:36
     */
    public interface HelloService {
    
        HelloDto getHello(String name);
    }
    

    2. 有了接口,肯定是需要实现类,并将getHello方法给予实现

    package cn.lonecloud.study;
    
    import cn.lonecloud.study.dto.HelloDto;
    import cn.lonecloud.study.service.HelloService;
    
    /**
     * @author lonecloud
     * @version v1.0
     * @Package cn.lonecloud.study
     * @Description: TODO
     * @date 2018/6/8下午11:35
     */
    public class HelloImpl implements HelloService {
        @Override
        public HelloDto getHello(String name) {
            return new HelloDto();
        }
    }  

    这两个硬性条件有了,则我们来编写动态代理类了

    1. 首先我们先来了解两个API:

      1. public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h):该类用于创建动态代理类的实例,

        1. loader:类的类加载器:一般用户类为AppClassLoader,可通过类名.class.getClassLoader()获得

        2. interfaces:接口数组,前面我们说过,jdk动态代理是基于接口来实现的,所以这个参数就是用来传递接口数组啦

        3. h:用于具体实现Handler,也就是这里执行相关的主要业务逻辑的地方了

      2. InvocationHandler:该接口用于实现动态代理类的相关业务逻辑

        1. 通常需要使用动态代理的话必须实现该接口,并重写其里面的invoke方法。

        2. invoke(Object proxy, Method method, Object[] args)throws Throwable; 

          1. proxy:代理类对象

          2. method:执行的方法

          3. args:相关的参数

    编写相关的代理类

    package cn.lonecloud.study;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    /**
     * @author lonecloud
     * @version v1.0
     * @Package cn.lonecloud.study
     * @Description: TODO
     * @date 2018/6/8下午11:23
     */
    public class ProxyDemo {
        //定义实现类对象
        Object target;
        //构造函数
        public ProxyDemo(Object target) {
            this.target = target;
        }
        //获取实现类方法
        @SuppressWarnings("unchecked")
        public <T> T getProxy(Class<T> clazz){
           //获取代理实例
            return(T) Proxy.newProxyInstance(clazz.getClassLoader(),new Class[]{clazz}, (proxy, method, args) -> {
                System.out.println(method.getName());
                //执行代理对象
                return method.invoke(target,args);
            });
        }
    }
    

      clazz.getClassLoader()获取的是类加载器,第二个参数创建了一个Class[]数组对象,由于传递过来的clazz为接口,所以可以这样写

    执行:

            HelloService proxy1 = new ProxyDemo(new HelloImpl()).getProxy(HelloService.class);
            HelloDto demo = proxy1.getHello("demo");
    

      该JDK动态代理的实现基本上就完成了,下一篇文章我们来看一下,jdk动态代理生产的字节码文件究竟是什么个样子

    深挖JDK动态代理(二):JDK动态生成后的字节码分析

  • 相关阅读:
    线程安全
    C++和java中构造函数与析构函数的调用顺序
    mysql数据库的备份与恢复
    Spring Web Flow 2.0 入门详解
    JBOSS 5.0与tomcat 6.0端口设置
    修改mysql root密码
    Subversion Native Library Not Available
    解决Eclipse导入svn项目自动关闭
    将eclipse中项目的Text File Encoding设置成为GBK
    java下实现调用oracle的存储过程和函数
  • 原文地址:https://www.cnblogs.com/lonecloud/p/9158459.html
Copyright © 2011-2022 走看看