深挖JDK动态代理

Posted lonecloud

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深挖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 动态代理(原理 + 代码实现)

jdk动态代理和cglib动态代理底层实现原理超详细解析(jdk动态代理篇)

JDK动态代理CGLIB动态代理

JDK动态代理CGLIB动态代理

(java反射-JDK动态代理)+CGLIB动态代理

JDK动态代理与Cglib动态代理