Spring系列七:JDK 动态代理和 CGLIB 代理

68 篇文章 2 订阅
67 篇文章 1 订阅
本文介绍了Spring AOP中的两种动态代理技术——JDK动态代理和CGLIB代理。JDK代理需要目标类实现接口,通过InvocationHandler实现横切逻辑;CGLIB则是通过字节码技术创建目标类的子类,适用于非接口类的代理,性能优于JDK代理但创建时间较长。文中还给出了JDK和CGLIB动态代理的简单应用场景及实现示例。
摘要由CSDN通过智能技术生成

JDK相信小伙伴们对它十分熟悉,那么小伙伴们知道JDK动态代理和CGLIB代理的区别吗?接下来由带领小伙伴对它们进行深入学习吧~~

21.说说JDK 动态代理和 CGLIB 代理 ?

Spring的AOP是通过动态代理来实现的,动态代理主要有两种方式JDK动态代理和Cglib动态代理,这两种动态代理的使用和原理有些不同。

JDK 动态代理

  1. Interface:对于 JDK 动态代理,目标类需要实现一个Interface。

  2. InvocationHandler:InvocationHandler是一个接口,可以通过实现这个接口,定义横切逻辑,再通过反射机制(invoke)调用目标类的代码,在次过程,可能包装逻辑,对目标方法进行前置后置处理。

  3. Proxy:Proxy利用InvocationHandler动态创建一个符合目标类实现的接口的实例,生成目标类的代理对象。

CgLib 动态代理

  1. 使用JDK创建代理有一大限制,它只能为接口创建代理实例,而CgLib 动态代理就没有这个限制。

  2. CgLib 动态代理是使用字节码处理框架ASM,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。

  3. CgLib创建的动态代理对象性能比 JDK 创建的动态代理对象的性能高不少,但是 CGLib 在创建代理对象时所花费的时间却比 JDK 多得多,所以对于单例的对象,因为无需频繁创建对象,用 CGLib 合适,反之,使用 JDK 方式要更为合适一些。同时,由于 CGLib 由于是采用动态创建子类的方法,对于 final 方法,无法进行代理。

我们来看一个常见的小场景,客服中转,解决用户问题:

用户向客服提问题

JDK动态代理实现:

JDK动态代理类图

  • 接口

    public?interface?ISolver?{
    ????void?solve();
    }
    
  • 目标类:需要实现对应接口

    public?class?Solver?implements?ISolver?{
    ????@Override
    ????public?void?solve()?{
    ????????System.out.println("疯狂掉头发解决问题……");
    ????}
    }
    
  • 态代理工厂:ProxyFactory,直接用反射方式生成一个目标对象的代理对象,这里用了一个匿名内部类方式重写InvocationHandler方法,实现接口重写也差不多

    public?class?ProxyFactory?{
    
    ????//?维护一个目标对象
    ????private?Object?target;
    
    ????public?ProxyFactory(Object?target)?{
    ????????this.target?=?target;
    ????}
    
    ????//?为目标对象生成代理对象
    ????public?Object?getProxyInstance()?{
    ????????return?Proxy.newProxyInstance(target.getClass().getClassLoader(),?target.getClass().getInterfaces(),
    ????????????????new?InvocationHandler()?{
    ????????????????????@Override
    ????????????????????public?Object?invoke(Object?proxy,?Method?method,?Object[]?args)?throws?Throwable?{
    ????????????????????????System.out.println("请问有什么可以帮到您?");
    
    ????????????????????????//?调用目标对象方法
    ????????????????????????Object?returnValue?=?method.invoke(target,?args);
    
    ????????????????????????System.out.println("问题已经解决啦!");
    ????????????????????????return?null;
    ????????????????????}
    ????????????????});
    ????}
    }
    
  • 客户端:Client,生成一个代理对象实例,通过代理对象调用目标对象方法

    public?class?Client?{
    ????public?static?void?main(String[]?args)?{
    ????????//目标对象:程序员
    ????????ISolver?developer?=?new?Solver();
    ????????//代理:客服小姐姐
    ????????ISolver?csProxy?=?(ISolver)?new?ProxyFactory(developer).getProxyInstance();
    ????????//目标方法:解决问题
    ????????csProxy.solve();
    ????}
    }
    

Cglib动态代理实现:

Cglib动态代理类图

  • 目标类:Solver,这里目标类不用再实现接口。

    public?class?Solver?{
    
    ????public?void?solve()?{
    ????????System.out.println("疯狂掉头发解决问题……");
    ????}
    }
    
  • 动态代理工厂:

    public?class?ProxyFactory?implements?MethodInterceptor?{
    
    ???//维护一个目标对象
    ????private?Object?target;
    
    ????public?ProxyFactory(Object?target)?{
    ????????this.target?=?target;
    ????}
    
    ????//为目标对象生成代理对象
    ????public?Object?getProxyInstance()?{
    ????????//工具类
    ????????Enhancer?en?=?new?Enhancer();
    ????????//设置父类
    ????????en.setSuperclass(target.getClass());
    ????????//设置回调函数
    ????????en.setCallback(this);
    ????????//创建子类对象代理
    ????????return?en.create();
    ????}
    
    ????@Override
    ????public?Object?intercept(Object?obj,?Method?method,?Object[]?args,?MethodProxy?proxy)?throws?Throwable?{
    ????????System.out.println("请问有什么可以帮到您?");
    ????????//?执行目标对象的方法
    ????????Object?returnValue?=?method.invoke(target,?args);
    ????????System.out.println("问题已经解决啦!");
    ????????return?null;
    ????}
    
    }
    
  • 客户端:Client

    public?class?Client?{
    ????public?static?void?main(String[]?args)?{
    ????????//目标对象:程序员
    ????????Solver?developer?=?new?Solver();
    ????????//代理:客服小姐姐
    ????????Solver?csProxy?=?(Solver)?new?ProxyFactory(developer).getProxyInstance();
    ????????//目标方法:解决问题
    ????????csProxy.solve();
    ????}
    }
    

先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值