深挖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动态代理的主要内容,如果未能解决你的问题,请参考以下文章