当前位置: 首页 > 网络应用技术

动态的代理机密,带您完全了解动态代理!

时间:2023-03-07 13:23:09 网络应用技术

  代理模式是一种设计模式,可以启用扩展源目标的功能,而无需修改源的源。,为了扩展功能,无需修改源代码。添加到代理类中。

  实际上,代理模式的核心思想很简单。在Java中,代理分为两种类型的静态代理和动态代理。其中,动态代理根据不同的实现区分了动态代理和基于子类的动态代理。

  由于静态代理相对简单,因此在采访中没有什么可问的。在代理模式下,最问的是动态代理,动态代理也是弹簧AOP的核心思想。春季的许多其他功能也通过动态试剂(例如Interceptor,Transaction Control等)实现。

  掌握动态代理技术可以使您的业务代码更加精简和优雅。如果您需要编写一些中间件,那么动态代理技术是必不可少的技能包。

  然后,本文使每个人都瞥见了动态代理的所有细节。

  在谈论动态代理之前,让我们谈谈静态代理。

  SO称为静态代理是通过声明明确的代理类访问源对象。

  我们有2个接口,人和动物。east接口有两个实现类别,UML如下所示:

  每个实现类中的代码几乎相同,例如使用学生给予它(其他类别几乎相同)

  假设我们现在必须做一件事,才能在所有实现类调用之前添加输出行,并在呼叫之前添加输出行。

  Personproxy:

  Animal -proxy:

  最终执行代码是:

  输出:

  综上所述:

  我认为,静态代理的代码不必说更多,代码非常简单易懂。此处使用了两个代理类,它们是代理和接口。

  尽管该模型易于理解,但缺点也很明显:

  动态代理,以流行的术语:No语句创建Java代理类,但在操作过程中生成了“虚拟”代理类,该类别由ClassLoader加载。因此,需要像静态代理一样声明大量代理类。

  JDK自1.3版以来就支持了动态代理类的创建,只有两个主要核心类别:和谐。

  仍然是上一个示例,使用JDK Dynamic Agency类实施的代码如下:

  为统一代理创建JDKProxy类:

  执行代码:

  解释:

  可以看出,与静态代理类相比,无论多少接口,只有一个代理。核心代码也很简单。唯一需要注意的点是以下2点:

  什么可以是代理商

  JDK的动态代理是每个人使用的最常见方法。此外,也称为Interface代理。几天前,一个小朋友问我小组中的我,动态代理是否可以一次代表一个类,并且可以多个类别。

  JDK Dynamic Agent说,它仅基于接口。在上述示例之前。只要您需要,您就可以构造本代理实现类的任何对象。某些接口。多个代理实例最终将输入以执行特定段落的常见代码的实现类。

  因此,以前项目中的实际场景之一是,我有许多常规文件由YAML定义,可以通过扫描YAML文件来为每个YAML规则文件生成动态代理类。要实现此功能,我只需要定义一个事先接口,定义实现类,同时,YAML已解析的对象被传递。最后,这些动态代理类将输入执行常见逻辑的方法。

  在5.x之前,Spring的默认动态代理一直是JDK动态代理。但是从5.x开始,Spring一直使用CGLIB作为动态代理。Springboot已从2.X转移到CGLIB动态代理的实现。

  是什么导致弹簧系统整体切换到CGLIB,JDK动态代理的缺点是什么?

  然后,我们需要谈论CGLIB的动态代理。

  CGLIB是一个开源项目。它的底层是字节代码处理框架ASM。CGLIB提供了比JDK更强大的动态代理。与JDK动态代理相比,主要的优势为:

  通过子类实现了什么?

  仍然是上一个示例,我们必须达到相同的效果。代码显示如下:

  为统一代理创建一个CGLIBPROXY类:

  执行代码:

  解释:

  在此处使用CGLIB作为代理,其思维类似于JDK动态代理。它还需要传递原始的Bean结构。原因是这里没有太多要重复的。

  关键代码在这里:

  可以看出,cglib“脱水”创建了原始bean的一个子类,并将回调指向此,即当前对象,即代理对象。因此,该方法被称为。,执行附加功能,并最终调用原始BEAN的相应方法。

  当调试生成的代理时,我们还可以看到CGLIB从稀薄的空气中生成原始豆的子类:

  Javassist是Java Bytecode类库的开源分析,编辑和创建,它可以直接编辑和生成由Java.com生成的字节代码。生成课程。

  在日常使用中,Javassit通常用于动态修改字节代码。它也可以用于实现动态代理的功能。

  没什么可说的,这是同一示例,我使用Javassist Dynamic代理再次实施

  为统一代理创建Javassitproxy:

  执行代码:

  解释:

  熟悉的公式,熟悉的口味大致相似。此外,可以看到Javassist还使用“生成子类”来解决它的方法。在代码末尾,调用原始bean的目标方法来完成代理。

  Javaassit更具特色是可以用过滤器设置它所需的代理,该代理可以像标准构造函数一样构造。

  Bytebuddy,bytecode的家伙,非常擅长听到。

  Bytebuddy也是一个著名的开源库。像cglib一样,它也基于ASM实施。还有一个名为Mockito的更著名的图书馆。我相信许多人使用这些东西来编写测试用例。核心基于字节缩。它可以动态生成模拟类,这非常方便。此外,另一个大应用程序字节是Java代理。它的主要功能是在加载类并插入自己的代码之前拦截它。

  Bytebuddy非常强大,可以将其应用于许多情况。但是在这里,只有Bytebuddy才被引入动态代理。关于其他使用方式,您可能必须写一篇特别的文章。在这里,您可以先挖自己的坑。

  来吧,一个熟悉的示例,一个熟悉的公式。使用bytebuddy再次实现上一个示例

  创建Bytebuddyproxy并做统一的代理:

  执行代码:

  解释:

  这个想法仍然和以前一样。通过仔细的观察代码,Bytebuddy还使用创意子类实现动态代理。

  早先引入了同一示例的四个动态剂的实现。代理模式可以分为两种类型:

  Spring5.x,SpringBoot2.x仅使用CGLIB作为动态代理的实现。它是CGLIB性能的最佳吗?

  我在这里做了一个简单而粗鲁的实验,并直接散发了单个线程的上述4段执行代码,并利用时间来确定其4个性能。您应该能够看到一些线索。

  公共班级Pronproxy实施人{

  傲慢的人;

  公共人员(人){

  this.person = person;

  }

  @Override

  public void wakeup(){

  system.out.println(“早安?”);

  person.wakeup();

  }

  @Override

  公共空白睡眠(){

  system.out.println(“晚安?”);

  person.sleep();

  }

  } 5执行结果如上

  从执行结果的角度来看,cglib是最好的效果。为什么Bytebuddy的执行速度如此之慢,不一定是Bytebuddy的性能不佳,或者可能是书面测试代码的问题,并且没有办法来找到正确的方法。因此,这只能用作粗略的参考。

  春季选择CGLIB似乎是有道理的。

  动态代理技术对于经常撰写开源或中间件的人来说是一种工件。此特征提供了新的解决方案。这使代码更加优雅和简单。DYNAGINIC代理也非常有助于理解春季的核心思想。希望对动态代理技术感兴趣的儿童鞋可以尝试在示例中运行代码以加强他们的理解。

  最后,附加了本文中使用的所有代码,我将其上传到Gitee:

  gitee.com/bryan31/proxy-demo

  如果您已经看到了这一点,认为本文可以帮助您,请喜欢并分享文章,并希望关注我的公共帐户。我是一位开源作者,他们将在业余时间分享技术和生活,并与您一起成长。

  作者:铂金说?