当前位置:首页 > 科技  > 软件

如何使用 CGLIB 在 Spring Boot 3.3 中实现动态代理

来源: 责编: 时间:2024-09-10 09:50:59 28观看
导读在 Java 开发中,代理模式是一种重要的设计模式,通过代理对象来控制对目标对象的访问。代理模式在 AOP(面向切面编程)中得到了广泛应用,尤其是在 Spring 框架中。Spring 提供了两种主要的代理机制:JDK 动态代理和 CGLIB 动态

在 Java 开发中,代理模式是一种重要的设计模式,通过代理对象来控制对目标对象的访问。代理模式在 AOP(面向切面编程)中得到了广泛应用,尤其是在 Spring 框架中。Spring 提供了两种主要的代理机制:JDK 动态代理和 CGLIB 动态代理。其中,JDK 动态代理仅能代理实现了接口的类,而 CGLIB 动态代理则没有这一限制,可以代理任何普通的类。因此,CGLIB 动态代理在实际开发中非常实用,特别是在需要代理没有实现接口的类时。tCi28资讯网——每日最新资讯28at.com

本文将深入探讨如何在 Spring Boot 3.3 中使用 CGLIB 实现动态代理。我们将通过具体的代码示例,展示如何在应用程序中集成 CGLIB,并解释其在 AOP 编程中的应用场景和优势。同时,我们还将展示如何通过前后端协作,将代理后的效果展示在 Web 页面上,从而帮助开发者更好地理解和运用 CGLIB 动态代理。tCi28资讯网——每日最新资讯28at.com

CGLIB 简介

CGLIB(Code Generation Library)是一个强大的高性能代码生成库,主要用于在运行时动态生成类和代理对象。CGLIB 通过使用底层的 ASM 字节码操纵框架,直接操作字节码文件,生成新的类或增强现有的类。与 JDK 动态代理不同,CGLIB 不需要目标类实现任何接口,这使得它在处理代理普通类时显得非常灵活和强大。tCi28资讯网——每日最新资讯28at.com

CGLIB 动态代理的工作原理是通过生成目标类的子类,并在子类中重写目标类的方法来实现对方法调用的拦截。CGLIB 可以在方法调用的前后添加自定义逻辑,例如日志记录、性能监控、事务管理等。这使得它在实现 AOP 编程时具有极大的优势,尤其是在 Spring 框架中被广泛应用。tCi28资讯网——每日最新资讯28at.com

值得注意的是,由于 CGLIB 是通过继承的方式实现代理,因此目标类不能是 final 的,否则会导致代理失败。此外,目标类中的 final 方法也无法被代理,因为 final 方法不能被重写。tCi28资讯网——每日最新资讯28at.com

运行效果:tCi28资讯网——每日最新资讯28at.com

图片图片tCi28资讯网——每日最新资讯28at.com

若想获取项目完整代码以及其他文章的项目源码,且在代码编写时遇到问题需要咨询交流,欢迎加入下方的知识星球。tCi28资讯网——每日最新资讯28at.com

项目结构

在开始之前,我们需要设置一个 Spring Boot 3.3 项目。项目结构如下:tCi28资讯网——每日最新资讯28at.com

cglib-demo├── src│   ├── main│   │   ├── java│   │   │   └── com│   │   │       └── icoderoad│   │   │           └── cglib│   │   │               ├── service│   │   │               │   └── CglibDemoService.java│   │   │               ├── proxy│   │   │               │   └── CglibProxy.java│   │   │               └── CglibDemoApplication.java│   │   └── resources│   │       ├── application.yaml│   │       └── templates│   │           └── index.html└── pom.xml

配置文件

pom.xml 配置

首先,在 pom.xml 文件中引入必要的依赖:tCi28资讯网——每日最新资讯28at.com

<?xml versinotallow="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">	<modelVersion>4.0.0</modelVersion>	<parent>		<groupId>org.springframework.boot</groupId>		<artifactId>spring-boot-starter-parent</artifactId>		<version>3.3.3</version>		<relativePath/> <!-- lookup parent from repository -->	</parent>	<groupId>com.icoderoad</groupId>	<artifactId>cglib-demo</artifactId>	<version>0.0.1-SNAPSHOT</version>	<name>cglib-demo</name>	<description>Demo project for Spring Boot</description>		<properties>		<java.version>17</java.version>	</properties>	<dependencies>		<!-- Spring Boot Starter Web -->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <!-- Spring Boot Thymeleaf -->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-thymeleaf</artifactId>        </dependency>        <!-- CGLIB Dependency -->        <dependency>		    <groupId>cglib</groupId>		    <artifactId>cglib-nodep</artifactId>		    <version>3.3.0</version> <!-- 或者更高的版本 -->		</dependency>        <!-- Bootstrap CSS -->        <dependency>            <groupId>org.webjars</groupId>            <artifactId>bootstrap</artifactId>            <version>5.3.0</version>        </dependency>		<dependency>			<groupId>org.springframework.boot</groupId>			<artifactId>spring-boot-starter-test</artifactId>			<scope>test</scope>		</dependency>	</dependencies>	<build>		<plugins>			<plugin>				<groupId>org.springframework.boot</groupId>				<artifactId>spring-boot-maven-plugin</artifactId>			</plugin>		</plugins>	</build></project>
application.yaml 配置

在 src/main/resources/application.yaml 文件中,我们可以加入一些简单的配置:tCi28资讯网——每日最新资讯28at.com

server:  port: 8080spring:  thymeleaf:    cache: false

CGLIB 动态代理实现

创建一个简单的服务类

首先,我们创建一个服务类 CglibDemoService,这个类将被代理:tCi28资讯网——每日最新资讯28at.com

package com.icoderoad.cglib_demo.service;public class CglibDemoService {    public String sayHello(String name) {        return "你好, " + name;    }    public String sayGoodbye(String name) {        return "再见, " + name;    }}
创建 CGLIB 代理类

接下来,我们创建一个 CGLIB 代理类 CglibProxy,用于拦截方法调用并进行处理:tCi28资讯网——每日最新资讯28at.com

package com.icoderoad.cglib_demo.proxy;import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;public class CglibProxy implements MethodInterceptor {    // 被代理的目标对象    private final Object target;    // 构造方法,传入目标对象    public CglibProxy(Object target) {        this.target = target;    }    // 拦截方法,在目标方法执行前后加入自定义逻辑    @Override    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {        System.out.println("方法执行前: " + method.getName());        Object result = proxy.invoke(target, args);        System.out.println("方法执行后: " + method.getName());        return result;    }    // 获取代理对象    public Object getProxy() {        Enhancer enhancer = new Enhancer();        enhancer.setSuperclass(target.getClass());        enhancer.setCallback(this);        return enhancer.create();    }}
使用代理类

在应用的启动类中,我们将使用 CglibProxy 来代理 CglibDemoService:tCi28资讯网——每日最新资讯28at.com

package com.icoderoad.cglib_demo;import org.springframework.boot.CommandLineRunner;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import com.icoderoad.cglib_demo.proxy.CglibProxy;import com.icoderoad.cglib_demo.service.CglibDemoService;@SpringBootApplicationpublic class CglibDemoApplication implements CommandLineRunner {	public static void main(String[] args) {        SpringApplication.run(CglibDemoApplication.class, args);    }    @Override    public void run(String... args) throws Exception {        CglibDemoService targetService = new CglibDemoService();        CglibProxy proxy = new CglibProxy(targetService);        CglibDemoService proxyService = (CglibDemoService) proxy.getProxy();                // 调用代理对象的方法        System.out.println(proxyService.sayHello("小明"));        System.out.println(proxyService.sayGoodbye("小明"));    }}

在这个例子中,我们通过 CglibProxy 代理 CglibDemoService,并在方法调用前后添加了自定义逻辑。tCi28资讯网——每日最新资讯28at.com

后端控制器

为了将数据传递到前端页面,我们需要创建一个控制器:tCi28资讯网——每日最新资讯28at.com

package com.icoderoad.cglib_demo.controller;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.GetMapping;import com.icoderoad.cglib_demo.proxy.CglibProxy;import com.icoderoad.cglib_demo.service.CglibDemoService;@Controllerpublic class DemoController {    @GetMapping("/")    public String index(Model model) {        // 创建目标对象        CglibDemoService demoService = new CglibDemoService();        // 创建代理对象        CglibProxy proxy = new CglibProxy(demoService);        CglibDemoService proxyService = (CglibDemoService) proxy.getProxy();        // 将方法调用结果传递给前端页面        model.addAttribute("helloMessage", proxyService.sayHello("路条编程"));        model.addAttribute("goodbyeMessage", proxyService.sayGoodbye("路条编程"));        return "index";    }}

前端页面展示

Thymeleaf 模板

在 src/main/resources/templates/index.html 文件中,创建一个简单的前端页面:tCi28资讯网——每日最新资讯28at.com

<!DOCTYPE html><html xmlns:th="http://www.thymeleaf.org"><head>    <meta charset="UTF-8">    <title>CGLIB 代理演示</title>    <link rel="stylesheet" th:href="@{/webjars/bootstrap/5.3.0/css/bootstrap.min.css}"></head><body><div class="container">    <h1>CGLIB 代理演示</h1>    <p th:text="'欢迎消息: ' + ${helloMessage}"></p>    <p th:text="'告别消息: ' + ${goodbyeMessage}"></p></div><script th:src="@{/webjars/bootstrap/5.3.0/js/bootstrap.bundle.min.js}"></script></body></html>

使用 --add-opens JVM 参数

在启动你的应用时,添加 --add-opens 参数以允许访问被封闭的模块:tCi28资讯网——每日最新资讯28at.com

java --add-opens java.base/java.lang=ALL-UNNAMED -jar your-application.jar

如果你是在 IDE 中运行应用程序,可以在 IDE 的运行配置中添加这个参数。tCi28资讯网——每日最新资讯28at.com

在 Eclipse 中配置 JVM 参数来解决 CGLIB 与 Java 模块系统兼容性问题,可以按照以下步骤操作:tCi28资讯网——每日最新资讯28at.com

配置 JVM 参数

  1. 打开 Eclipse 项目属性
  • 在 Eclipse 中,右键点击你的项目,选择 Properties(属性)。
  1. 进入 Run/Debug Settings
  • 在左侧面板中,选择 Run/Debug Settings。tCi28资讯网——每日最新资讯28at.com

  1. 选择或创建运行配置tCi28资讯网——每日最新资讯28at.com

  • 如果已有运行配置,选择你要修改的配置,然后点击 Edit(编辑)。tCi28资讯网——每日最新资讯28at.com

  • 如果没有,点击 New Configuration(新建配置),然后选择 Java Application 或 Spring Boot App,点击 New(新建)。tCi28资讯网——每日最新资讯28at.com

  1. 配置 VM ArgumentstCi28资讯网——每日最新资讯28at.com

  • 在 Arguments 标签页中,找到 VM arguments 输入框。在这里你可以添加 JVM 启动参数。tCi28资讯网——每日最新资讯28at.com

  • 在 VM arguments 输入框中,添加如下参数:tCi28资讯网——每日最新资讯28at.com

    --add-opens java.base/java.lang=ALL-UNNAMED
  • 这个参数允许你访问 Java 内部 API,解决 CGLIB 在模块系统中的兼容性问题。tCi28资讯网——每日最新资讯28at.com

  1. 保存配置tCi28资讯网——每日最新资讯28at.com

  • 点击 Apply(应用),然后点击 Run(运行)以保存并应用你的配置。tCi28资讯网——每日最新资讯28at.com

运行效果

启动 Spring Boot 项目后,访问 http://localhost:8080,页面上将显示通过 CGLIB 动态代理处理后的消息,控制台中可以看到方法执行前后的日志输出。tCi28资讯网——每日最新资讯28at.com

总结

本文详细介绍了如何在 Spring Boot 3.3 中使用 CGLIB 实现动态代理。通过实际的代码示例,展示了 CGLIB 在动态代理中的应用,以及如何在 Spring Boot 项目中集成 CGLIB。我们还演示了如何通过 Thymeleaf 和 Bootstrap 实现一个简单的前端页面,以展示代理后的效果。希望通过这篇文章,您能对 CGLIB 动态代理有一个更深入的理解。tCi28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-112781-0.html如何使用 CGLIB 在 Spring Boot 3.3 中实现动态代理

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 超赞!Spring Boot 3.3 自带 Controller 接口监控,大家赶紧用起来

下一篇: Java8 中一个极其强悍的新接口,很多人没用过

标签:
  • 热门焦点
  • 7月安卓手机性能榜:红魔8S Pro再夺榜首

    7月安卓手机性能榜:红魔8S Pro再夺榜首

    7月份的手机市场风平浪静,除了红魔和努比亚带来了两款搭载骁龙8Gen2领先版处理器的新机之外,别的也想不到有什么新品了,这也正常,通常6月7月都是手机厂商修整的时间,进入8月份之
  • 5月iOS设备性能榜:M1 M2依旧是榜单前五

    5月iOS设备性能榜:M1 M2依旧是榜单前五

    和上个月一样,没有新品发布的iOS设备性能榜的上榜设备并没有什么更替,仅仅只有跑分变化而产生的排名变动,刚刚开始的苹果WWDC2023,推出的产品也依旧是新款Mac Pro、新款Mac Stu
  • 5月安卓手机好评榜:魅族20 Pro夺冠

    5月安卓手机好评榜:魅族20 Pro夺冠

    性能榜和性价比榜之后,我们来看最后的安卓手机好评榜,数据来源安兔兔评测,收集时间2023年5月1日至5月31日,仅限国内市场。第一名:魅族20 Pro好评率:97.50%不得不感慨魅族老品牌还
  • 5月iOS设备好评榜:iPhone 14仅排第43?

    5月iOS设备好评榜:iPhone 14仅排第43?

    来到新的一月,安兔兔的各个榜单又重新汇总了数据,像安卓阵营的榜单都有着比较大的变动,不过iOS由于设备的更新换代并没有那么快,所以相对来说变化并不大,特别是iOS好评榜,老款设
  • JavaScript 混淆及反混淆代码工具

    JavaScript 混淆及反混淆代码工具

    介绍在我们开始学习反混淆之前,我们首先要了解一下代码混淆。如果不了解代码是如何混淆的,我们可能无法成功对代码进行反混淆,尤其是使用自定义混淆器对其进行混淆时。什么是混
  • Flowable工作流引擎的科普与实践

    Flowable工作流引擎的科普与实践

    一.引言当我们在日常工作和业务中需要进行各种审批流程时,可能会面临一系列技术和业务上的挑战。手动处理这些审批流程可能会导致开发成本的增加以及业务复杂度的上升。在这
  • 虚拟键盘 API 的妙用

    虚拟键盘 API 的妙用

    你是否在遇到过这样的问题:移动设备上有一个固定元素,当激活虚拟键盘时,该元素被隐藏在了键盘下方?多年来,这一直是 Web 上的默认行为,在本文中,我们将探讨这个问题、为什么会发生
  • 东方甄选单飞:有些鸟注定是关不住的

    东方甄选单飞:有些鸟注定是关不住的

    作者:彭宽鸿来源:华尔街科技眼&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;东方甄选创始人俞敏洪带队的&ldquo;7天甘肃行&rdquo;直播活动已在近日顺利收官。成立后一
  • 7月4日见!iQOO 11S官宣:“鸡血版”骁龙8 Gen2+200W快充加持

    7月4日见!iQOO 11S官宣:“鸡血版”骁龙8 Gen2+200W快充加持

    上半年已接近尾声,截至目前各大品牌旗下的顶级旗舰都已悉数亮相,而下半年即将推出的顶级旗舰已经成为了数码圈爆料的主流,其中就包括全新的iQOO 11S系
Top