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

JDK动态代理和CGLIB动态代理案例分析

 JDK动态代理和CGLIB动态代理案例分析

JDK动态代理和CGLIB动态代理的实现原理如下:

  1. JDK动态代理的实现原理:

    • JDK动态代理是基于Java的反射机制实现的
    • 实现一个继承InvocationHandler接口的对象,重写invoke方法,invoke方法中可以在目标方法执行前后添加一些额外的逻辑,该对象负责处理代理对象的方法调用。
    • 当使用JDK动态代理时,通过Proxy类的newProxyInstance方法创建代理对象,需要传入三个参数,分别是目标对象的类加载器、接口列表和一个实现了`InvocationHandler`接口的对象。
    • 在代理对象的方法被调用时,InvocationHandlerinvoke方法会被触发,通过反射机制调用目标对象的方法。
  2. CGLIB动态代理的实现原理:

    • CGLIB动态代理使用字节码增强技术实现。
    • 在运行时,CGLIB通过继承目标对象的子类来创建代理对象。
    • CGLIB通过操作字节码,在子类中重写目标对象的方法,并在重写的方法中添加额外的逻辑。
    • 通过创建子类的实例作为代理对象,实现对目标对象方法的代理。

JDK动态代理适用于目标对象实现了接口的情况,而CGLIB动态代理适用于目标对象没有实现接口的情况。根据具体的需求和场景,选择合适的动态代理方式来实现代理功能。

JDK动态代理

当使用JDK动态代理时,我们需要以下步骤来实现代理:

1. 定义一个接口,例如`UserService`,并在接口中声明需要代理的方法。

public interface UserService {void saveUser(String username);
}

2. 创建一个实现了`InvocationHandler`接口的类,例如`UserInvocationHandler`,该类负责处理代理对象的方法调用。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;public class UserInvocationHandler implements InvocationHandler {private Object target;public UserInvocationHandler(Object target) {this.target = target;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("Before method: " + method.getName());Object result = method.invoke(target, args);System.out.println("After method: " + method.getName());return result;}
}

3. 在主程序中使用`Proxy`类的`newProxyInstance`方法创建代理对象。

import java.lang.reflect.Proxy;public class JDKDynamicProxyExample {public static void main(String[] args) {UserService userService = new UserServiceImpl();UserService proxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),userService.getClass().getInterfaces(),new UserInvocationHandler(userService));proxy.saveUser("John");}
}

在以上代码中,我们首先创建了一个实现了`InvocationHandler`接口的类`UserInvocationHandler`,它接收一个目标对象作为参数。在`invoke`方法中,我们可以在目标方法调用前后添加额外的逻辑。

然后,在主程序中,我们创建了一个`UserService`的实现类对象`userService`,然后通过`Proxy.newProxyInstance`方法创建了一个代理对象。在创建代理对象时,我们传入了目标对象的类加载器、接口列表和一个实现了`InvocationHandler`接口的对象`UserInvocationHandler`。

最后,我们调用代理对象的方法`saveUser`,在方法调用前后,`invoke`方法中的逻辑会被触发。

这就是JDK动态代理的实现原理的一个简单示例。通过代理对象,我们可以在目标方法调用前后添加额外的逻辑,实现对目标对象方法的代理。

CGLIB动态代理

为了使用CGLIB动态代理,需要引入CGLIB库。以下是使用CGLIB动态代理的示例代码:

1. 首先,确保您的项目中引入了CGLIB库。您可以在Maven项目中添加以下依赖:

<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>

2. 定义一个目标类`UserServiceImpl`,它是没有实现接口的普通类。

public class UserServiceImpl {public void saveUser(String username) {System.out.println("Saving user: " + username);}
}

3. 创建一个实现了`MethodInterceptor`接口的类`UserMethodInterceptor`,重写intercept方法,intercept方法中可以在目标方法执行前后添加一些额外的逻辑,该类负责处理代理对象的方法调用。

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class UserMethodInterceptor implements MethodInterceptor {public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("Before method: " + method.getName());Object result = proxy.invokeSuper(obj, args);System.out.println("After method: " + method.getName());return result;}
}

4. 在主程序中使用CGLIB来创建代理对象。

import net.sf.cglib.proxy.Enhancer;public class CGLIBDynamicProxyExample {public static void main(String[] args) {UserServiceImpl userService = new UserServiceImpl();UserServiceImpl proxy = (UserServiceImpl) Enhancer.create(userService.getClass(),new UserMethodInterceptor());proxy.saveUser("John");}
}

在以上代码中,我们首先创建了一个实现了`MethodInterceptor`接口的类`UserMethodInterceptor`,它负责处理代理对象的方法调用。在`intercept`方法中,我们可以在目标方法调用前后添加额外的逻辑。

然后,在主程序中,我们创建了一个`UserServiceImpl`的实例对象`userService`,然后通过`Enhancer.create`方法创建了一个代理对象。在创建代理对象时,我们传入了目标对象的类和一个实现了`MethodInterceptor`接口的对象`UserMethodInterceptor`。

最后,我们调用代理对象的方法`saveUser`,在方法调用前后,`intercept`方法中的逻辑会被触发。

这就是CGLIB动态代理的实现原理的一个简单示例。通过代理对象,我们可以在目标方法调用前后添加额外的逻辑,实现对目标对象方法的代理。

http://www.lryc.cn/news/424174.html

相关文章:

  • 【数据结构-前缀哈希】力扣1124. 表现良好的最长时间段
  • 电商平台产品ID|CDN与预渲染|前端边缘计算
  • LATTICE进阶篇DDR2--(4)DDR2 IP核总结
  • windows下php安装kafka
  • 【wiki知识库】09.欢迎页面展示(浏览量统计)SpringBoot部分
  • 数据分析与应用:微信-情人节红包流向探索分析
  • SQL,获取 ID 的历史状态
  • 阅文集团:摇不动的IP摇钱树
  • ETL数据集成丨将SQL Server数据同步至Oracle的具体实现
  • 20240814软考架构-------软考51-55答案解析
  • JavaEE 的入门
  • vue3+ts 前端word文档下载文件时不预览直接下载方法(支持 doc / excel / ppt / pdf 等)
  • Java 空值与null 形参与实参学习
  • 【QT常用技术讲解】QTableView添加QCheckBox、QPushButton
  • linux监控命令
  • SpringBoot入门笔记
  • python 华为od 单词接龙
  • Vue+Echart实现地图省市区三级下钻
  • Apache Tomcat 信息泄露漏洞排查处理CVE-2024-21733)
  • 51单片机-LED实验
  • 无人机开启农林植保新篇章
  • 第N4周:NLP中的文本嵌入
  • C++高精度减法
  • protobuf cmakelist,msvc utf-8设置
  • Haproxy讲解
  • K8S系列——一、Ubuntu上安装Helm
  • 排序: 插入\希尔\选择\归并\冒泡\快速\堆排序实现
  • OpenCV图像处理——按最小外接矩形剪切图像处理ROI后映射回原图像
  • Linux中以单容器部署Nginx+ASP.NET Core
  • 【秋招笔试】8.11大疆秋招(第三套)-三语言题解