JKD动态代理

一、说明

在Java的动态代理机制中,有两个重要的类和接口,一个是InvoInvocationHandler(接口)、Proxy(类),这一个类和接口是我们动态代理所必须用到的。

在这里插入图片描述

优点:

  • 对于实现了接口的类,可以直接使用基于接口的动态代理进行代理,非常方便
  • 代理类和被代理类都必须实现同一个接口,能够实现对被代理对象的方法调用进行统一管理。
  • 性能上:在老版的jdk,jdk代理生成的类速度快,通过反射调用慢,cglib是jdk代理速度的10倍左右,jdk在版本每次升级都会有很大的性能提升,cglib停滞不前,jdk7 8的动态代理性能在1万次实验中比cglib要快20%左右
  • jdk动态代理如果目标类未实现接口则无法代理,cglib是通过继承的方式来动态代理,若目标类被final关键字修饰,则无法使用cglib做动态代理

缺点:

  • 只能代理实现了接口的类,对于没有实现接口的类无法使用此种方式进行代理。
  • jdk动态代理只提供实现接口的目标类代理,不支持没有实现接口的目标类的代理。如果目标类没有实现接口,只能用cglib代理

二、主要类方法的说明

InvocationHandler接口:

每个动态代理类都必须实现InvocationHandler接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler接口的invoke方法来进行调用。

InvocationHandler接口的invoke方法
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
proxy:  - 指代我们所代理的那个真实对象
method: - 指代的是我们所要调用真实对象的某个方法的Method对象
args:  - 指代的是调用真实对象某个方法时接受的参数

**proxy存在的意义:**
1. 可以使用反射获取代理对象的信息(也就是proxy.getClass().getName())。
2. 可以将代理对象返回以进行连续调用,这就是proxy存在的目的,因为this并不是代理对象。

Proxy 类:

Proxy类的作用就是用来动态创建一个代理类对象的类,它提供了许多的方法,但是我们用的最多的就是newProxyInstance这个方法

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
loader:   一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
interfaces:  一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
h:   一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
  • 打印代理的类:
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

三、关键步骤

  1. 创建InvocationHandler实现类
public class MapperProxy<T> implements InvocationHandler {
      private Class<T> proxyInterface;
    //这里可以维护一个缓存,存这个接口的方法抽象的对象
    MapperProxy(Class<T> proxyInterface){
        this.proxyInterface = proxyInterface;
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("执行前...");
        Constructor constructor  = proxyInterface.getConstructor();
        Object o =  constructor.newInstance();
        method.invoke(o,args);
        System.out.println("执行后");
        return null;
    }
}
  1. 通过 Proxy.newProxyInstance() 创建代理实例
 Fly fly = (Fly) Proxy.newProxyInstance(MyFly.class.getClassLoader(),new Class[]{Fly.class, Fly.Fly2.class},new MapperProxy<>(MyFly.class));

在这里插入图片描述

-  创建代理类-   Class<?> cl = getProxyClass0(loader, intfs);
-  获取有参构造器  Constructor<?> cons = cl.getConstructor(constructorParams);这里的参数就是InvocationHandler
-  通过构造器创建代理实例-参数就是方法的第三个参数
  1. 分析生成的代理类
    在这里插入图片描述
    在这里插入图片描述
结论:
  • 代理类会继承Proxy ,这里也就解释了为什么通过JDK生成的代理无法代理非接口实现类了
  • 代理类实现了传入的所有接口类型
  1. 调用代理类的doFly()
  • 这里会调用 super.h.invoke(this, m3, (Object[])null);
  • super.h就是我们再创建代理对象是传入的MapperProxy,所有这里会执行MapperProxy.invoke方法(在这里我们就可动态的对该执行方法进行增强)
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值