代理模式———静态代理、动态代理(JDK代理)、CGLIB代理

2024-09-06 09:58

本文主要是介绍代理模式———静态代理、动态代理(JDK代理)、CGLIB代理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、代理模式

代理模式就是为某个对象Q,提供一个代理对象,通过代理对象,完成对对象Q的引用。

通过代理对象的增强可以无侵入的扩展委托类。真正的业务实现还是交与委托类,代理类相当于包装了一层委托类,可以在委托类执行的前后加入扩展,比如缓存,切面,消息等。

在SpringAOP的实现中,使用的核心技术就是动态代理,使用了JDK代理(对象实现了接口使用)与CGLIB(对象没实现接口使用)代理的结合。

 

二、静态代理

 如上图所示,代理类和目标对象分别实现相同的接口。代理对象调用实现类,完成方法的调用和封装。

优点:

  • 可以做到不修改目标对象的情况下,对目标功能扩展

缺点:

  • 每个目标对象都需要一个代理类。
  • 接口每增加一个方法,都需要同时改动,代理类与目标对象。
  • (不用接口实现代理的是委托模式,直接用另一个对象包装,目标对象)

三、动态代理

动态代理也叫jdk代理,接口代理。

特点:

  • jdk 调用jdk,API接口,动态生成代理对象
  • 代理对象不需要实现接口

上代码

代理对象:                                                                                        调用:

JDK实现代理只需要使用newProxyInstance方法

这个方法需要三个参数:

  • ClassLoader loader,:定义代理类的类加载器
  • Class<?>[] interfaces,:代理类的实现接口集合
  • InvocationHandler h:调用方法时的调用处理器

根据这个newProxyInstance()方法会动态的创建出,代理对象

优点:

  •     代理类不需要实现接口
  •     相比静态代理,运行时生成代理对象,可在运行时指定代理的目标对象,和代理的逻辑。相比静态代理更加灵活,静态代理在编译期以及指定了,代理的目标对象和代理逻辑。
  •     可以任意指定目标对象,和代理逻辑。

缺点:

  • 目标对象需要实现对应的接口,没有接口的类,无法实现jdk动态代理。

四、CGLib代理

CGLib代理也叫做子类代理类。

CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。但因为采用的是继承,所以不能对final修饰的类进行代理。

特点:

  • 可以对无接口的类实现代理
  • 代理的类不能为final,否则报错
  • 目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.
public class CglibProxy implements MethodInterceptor {private Object target;//业务类对象,供代理方法中进行真正的业务方法调用//    //获得一个代理对象public Object getProxyInstance(Object target){this.target =target;//给业务对象赋值//1.工具类Enhancer en = new Enhancer();//创建加强器,用来创建动态代理类//2.设置父类en.setSuperclass(this.target.getClass());//为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)//设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦//3.设置回调函数en.setCallback(this);//4.创建子类(代理对象)return en.create();}@Overridepublic Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {System.out.println("代理对象调用前处理");Object result =  methodProxy.invoke(o,args);//调用业务类(父类中)的方法System.out.println("代理对象调用后处理");return result;}
}
调用
  //3.cglib代理SubjectCGImpl target = new SubjectCGImpl();CglibProxy cglibProxy = new CglibProxy();SubjectCGImpl proxyInstance = (SubjectCGImpl)cglibProxy.getProxyInstance(target);proxyInstance.requ11est();

 这里调用的时候还会出现堆栈溢出的问题,目前还没找到原因。

CGLIB动态代理的性能比JDK动态代理的性能高10倍左右,但创建代理对象的速度却比JDK创建代理对象的速度慢15倍左右。对单利的代理对象创建使用CGLIB更合适。

 

这篇关于代理模式———静态代理、动态代理(JDK代理)、CGLIB代理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1141704

相关文章

SpringBoot中@Value注入静态变量方式

《SpringBoot中@Value注入静态变量方式》SpringBoot中静态变量无法直接用@Value注入,需通过setter方法,@Value(${})从属性文件获取值,@Value(#{})用... 目录项目场景解决方案注解说明1、@Value("${}")使用示例2、@Value("#{}"php

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

解决升级JDK报错:module java.base does not“opens java.lang.reflect“to unnamed module问题

《解决升级JDK报错:modulejava.basedoesnot“opensjava.lang.reflect“tounnamedmodule问题》SpringBoot启动错误源于Jav... 目录问题描述原因分析解决方案总结问题描述启动sprintboot时报以下错误原因分析编程异js常是由Ja

C#和Unity中的中介者模式使用方式

《C#和Unity中的中介者模式使用方式》中介者模式通过中介者封装对象交互,降低耦合度,集中控制逻辑,适用于复杂系统组件交互场景,C#中可用事件、委托或MediatR实现,提升可维护性与灵活性... 目录C#中的中介者模式详解一、中介者模式的基本概念1. 定义2. 组成要素3. 模式结构二、中介者模式的特点

通过配置nginx访问服务器静态资源的过程

《通过配置nginx访问服务器静态资源的过程》文章介绍了图片存储路径设置、Nginx服务器配置及通过http://192.168.206.170:8007/a.png访问图片的方法,涵盖图片管理与服务... 目录1.图片存储路径2.nginx配置3.访问图片方式总结1.图片存储路径2.nginx配置

Linux系统中查询JDK安装目录的几种常用方法

《Linux系统中查询JDK安装目录的几种常用方法》:本文主要介绍Linux系统中查询JDK安装目录的几种常用方法,方法分别是通过update-alternatives、Java命令、环境变量及目... 目录方法 1:通过update-alternatives查询(推荐)方法 2:检查所有已安装的 JDK方

在macOS上安装jenv管理JDK版本的详细步骤

《在macOS上安装jenv管理JDK版本的详细步骤》jEnv是一个命令行工具,正如它的官网所宣称的那样,它是来让你忘记怎么配置JAVA_HOME环境变量的神队友,:本文主要介绍在macOS上安装... 目录前言安装 jenv添加 JDK 版本到 jenv切换 JDK 版本总结前言China编程在开发 Java

go动态限制并发数量的实现示例

《go动态限制并发数量的实现示例》本文主要介绍了Go并发控制方法,通过带缓冲通道和第三方库实现并发数量限制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录带有缓冲大小的通道使用第三方库其他控制并发的方法因为go从语言层面支持并发,所以面试百分百会问到

JAVA中安装多个JDK的方法

《JAVA中安装多个JDK的方法》文章介绍了在Windows系统上安装多个JDK版本的方法,包括下载、安装路径修改、环境变量配置(JAVA_HOME和Path),并说明如何通过调整JAVA_HOME在... 首先去oracle官网下载好两个版本不同的jdk(需要登录Oracle账号,没有可以免费注册)下载完

一文详解SpringBoot中控制器的动态注册与卸载

《一文详解SpringBoot中控制器的动态注册与卸载》在项目开发中,通过动态注册和卸载控制器功能,可以根据业务场景和项目需要实现功能的动态增加、删除,提高系统的灵活性和可扩展性,下面我们就来看看Sp... 目录项目结构1. 创建 Spring Boot 启动类2. 创建一个测试控制器3. 创建动态控制器注