当前位置: 首页 > news >正文

Java jdk版动态代理介绍

一、概述

动态代理(Dynamic Proxy)是一种在运行时动态创建代理对象的技术,允许你在不修改原始类代码的情况下,为某个对象提供额外的行为。动态代理广泛应用于各种场景,如日志记录、事务管理、权限检查等。在 Java 中,动态代理主要通过 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口来实现。

动态代理使用了代理模式的思想:

  • 代理模式是一种设计模式,用于在不改变原始对象的情况下,为其提供一个代理对象,以便在访问原始对象时增加额外的操作。
  • 代理对象和原始对象实现相同的接口,这样客户端可以通过代理对象间接访问原始对象。

二、静态代理

在说动态代理之前,先来讲一件静态代理。与动态代理不同,静态代理在编译时就需要定义好代理类和被代理类,因此灵活性较低,但实现相对简单。

如以下需求:有一个接口MyService,其中有一个方法为add,实现两数相加。

//定义接口
public interface MyService {int add(int a,int b);
}
//定于实现类
public class MyServiceImpl {public int add(int a,int b){return a+b; }
}

现在要求在这个方法执行前后输出一些话,此时可以自定义一个静态代理类来实现。让该静态代理类去继承MyService接口,从而可以通过该代理类来间接调用方法,并且可以在方法执行前后执行一些其他的操作,如打印日志。

public class MyServiceProxy implements MyService {//所要代理执行的目标对象private  MyService target;public MyServiceProxy(MyService target) {this.target = target;}@Overridepublic int add(int a,int b) {// 在方法调用前添加额外的行为System.out.println("Before method");// 调用目标对象的方法target.add(a,b);// 在方法调用后添加额外的行为System.out.println("After method");}
}

如此,我们便可以通过该代理类的add方法来间接调用目标方法,并且增添了一些操作。

三、通过JKD自带的类实现动态代理

我们可以发现,之前的动态代理虽然可以实现,但是如果需求一改变,比如在执行前打印参数信息,那么就得修改源码或者再写一个代理类,非常的不灵活。这下就可以使用动态代理来实现了。

java.lang.reflect.Proxy中的一个静态方法newProxyInstance可以动态的创建一个动态代理对象。

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) {...
}

这个方法有三个参数:

  • ClassLoader loader: 目标对象的类加载器
  • Class<?>[] interfaces: 目标对象所实现的接口
  • InvocationHandler h:这个是重点,单独来说。

InvocationHandler: 这是一个接口,用于处理方法调用。里面只有一个抽象方法,是一个函数式接口

public interface InvocationHandler {public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;...
}

invoke就是我们所需要重写的函数,它有三个参数,分别表示:

  • Object proxy :这是目标对象所关联的代理类对象,当通过代理类对象来间接调用方法时,就会执行invoke函数。
  • Method method: 这是想要目标对象执行的方法
  • Object[] args:这是执行目标对象方法所传入的参数

现在我们就可以通过使用动态代理来改进上述案例.

public class DynamicProxyExample {public static void main(String[] args) {//创建目标对象MyService target=new MyServiceImpl();InvocationHandler handler=new InvocationHandler() {@Override//在这里我们可以在执行目标方法前后为其增加一些额外的操作public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 在方法调用前添加额外的行为System.out.println("Before method");//通过反射来调用目标对象的方法method.invoke(target);// 在方法调用后添加额外的行为System.out.println("After method");}}// 创建动态代理对象MyService proxy = (MyService) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),handler);//执行目标方法int result=proxy.add(1,2);System.out.println(result);}
} 

结果为:

Before method
3
After method

由于InvocationHandle是一个函数式接口,过也可以用Lombda表达式来实现。

MyService proxy = (MyService) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),(proxy,method,args)->{System.out.println("Before method");method.invoke(target);System.out.println("After method");}
);

总的来说通过动态代理,可以在不修改原有业务逻辑的情况下,为对象添加额外的功能,提高代码的灵活性和可维护性。

注意:使用JDK自带的类来实现动态代理时,要求目标类必须实现接口!!!


http://www.mrgr.cn/news/59443.html

相关文章:

  • docker配置普通用户访问
  • 别名联想路径,前端项目输入@/自动出提示目录和文件
  • 十分钟了解Android Handler、Looper、Message
  • 《C++音频频谱分析:开启声音世界的神秘之门》
  • 【UE5】将2D切片图渲染为体积纹理,最终实现使用RT实时绘制体积纹理【第七篇-体积纹理绘制】
  • XPM_CDC_SINGLE
  • 数组指针
  • Python中,lambda函数的用法是什么?
  • 拉斯维加斯算法(Las Vegas Algorithm)详细解读
  • Node.js 循环依赖或者递归调用导致的堆栈溢出问题
  • learn C++ NO.29——智能指针
  • 通过IPAM进行IP地址规划和管理
  • Java面试题——计网篇2
  • 【数学二】多元函数积分学-重积分-二重积分定义、性质、计算
  • (50)MATLAB最优延迟迫零均衡器仿真测试与评估
  • React前端框架 – 全面了解与应用
  • [专有网络VPC]创建和管理网络ACL
  • 医疗实施-项目管理06-估算成本
  • Windows 11 绕过 TPM 方法总结,24H2 通用免 TPM 镜像下载 (Updated Oct 2024)
  • Java 泛型
  • PMP--一、二、三模、冲刺、必刷--分类--10.沟通管理--技巧--文化意识
  • 012:无人机航测相关知识点整理
  • 碳中和技术:实现可持续未来的关键
  • 【Linux 从基础到进阶】数据库高可用与灾备方案
  • Spring 版本更新
  • ATom:2016-2018 年沿飞行轨迹的 CAM-chem/CESM2 模型输出