自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何使用 CGLIB 在 Spring Boot 3.3 中實現動態(tài)代理

開發(fā) 前端
本文詳細介紹了如何在 Spring Boot 3.3 中使用 CGLIB 實現動態(tài)代理。通過實際的代碼示例,展示了 CGLIB 在動態(tài)代理中的應用,以及如何在 Spring Boot 項目中集成 CGLIB。

在 Java 開發(fā)中,代理模式是一種重要的設計模式,通過代理對象來控制對目標對象的訪問。代理模式在 AOP(面向切面編程)中得到了廣泛應用,尤其是在 Spring 框架中。Spring 提供了兩種主要的代理機制:JDK 動態(tài)代理和 CGLIB 動態(tài)代理。其中,JDK 動態(tài)代理僅能代理實現了接口的類,而 CGLIB 動態(tài)代理則沒有這一限制,可以代理任何普通的類。因此,CGLIB 動態(tài)代理在實際開發(fā)中非常實用,特別是在需要代理沒有實現接口的類時。

本文將深入探討如何在 Spring Boot 3.3 中使用 CGLIB 實現動態(tài)代理。我們將通過具體的代碼示例,展示如何在應用程序中集成 CGLIB,并解釋其在 AOP 編程中的應用場景和優(yōu)勢。同時,我們還將展示如何通過前后端協作,將代理后的效果展示在 Web 頁面上,從而幫助開發(fā)者更好地理解和運用 CGLIB 動態(tài)代理。

CGLIB 簡介

CGLIB(Code Generation Library)是一個強大的高性能代碼生成庫,主要用于在運行時動態(tài)生成類和代理對象。CGLIB 通過使用底層的 ASM 字節(jié)碼操縱框架,直接操作字節(jié)碼文件,生成新的類或增強現有的類。與 JDK 動態(tài)代理不同,CGLIB 不需要目標類實現任何接口,這使得它在處理代理普通類時顯得非常靈活和強大。

CGLIB 動態(tài)代理的工作原理是通過生成目標類的子類,并在子類中重寫目標類的方法來實現對方法調用的攔截。CGLIB 可以在方法調用的前后添加自定義邏輯,例如日志記錄、性能監(jiān)控、事務管理等。這使得它在實現 AOP 編程時具有極大的優(yōu)勢,尤其是在 Spring 框架中被廣泛應用。

值得注意的是,由于 CGLIB 是通過繼承的方式實現代理,因此目標類不能是 final 的,否則會導致代理失敗。此外,目標類中的 final 方法也無法被代理,因為 final 方法不能被重寫。

運行效果:

圖片圖片

若想獲取項目完整代碼以及其他文章的項目源碼,且在代碼編寫時遇到問題需要咨詢交流,歡迎加入下方的知識星球。

項目結構

在開始之前,我們需要設置一個 Spring Boot 3.3 項目。項目結構如下:

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 文件中引入必要的依賴:

<?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 文件中,我們可以加入一些簡單的配置:

server:
  port: 8080

spring:
  thymeleaf:
    cache: false

CGLIB 動態(tài)代理實現

創(chuàng)建一個簡單的服務類

首先,我們創(chuàng)建一個服務類 CglibDemoService,這個類將被代理:

package com.icoderoad.cglib_demo.service;

public class CglibDemoService {

    public String sayHello(String name) {
        return "你好, " + name;
    }

    public String sayGoodbye(String name) {
        return "再見, " + name;
    }
}
創(chuàng)建 CGLIB 代理類

接下來,我們創(chuàng)建一個 CGLIB 代理類 CglibProxy,用于攔截方法調用并進行處理:

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;
    }

    // 攔截方法,在目標方法執(zhí)行前后加入自定義邏輯
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("方法執(zhí)行前: " + method.getName());
        Object result = proxy.invoke(target, args);
        System.out.println("方法執(zhí)行后: " + method.getName());
        return result;
    }

    // 獲取代理對象
    public Object getProxy() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }
}
使用代理類

在應用的啟動類中,我們將使用 CglibProxy 來代理 CglibDemoService:

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;

@SpringBootApplication
public 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,并在方法調用前后添加了自定義邏輯。

后端控制器

為了將數據傳遞到前端頁面,我們需要創(chuàng)建一個控制器:

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;

@Controller
public class DemoController {

    @GetMapping("/")
    public String index(Model model) {
        // 創(chuàng)建目標對象
        CglibDemoService demoService = new CglibDemoService();
        // 創(chuàng)建代理對象
        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 文件中,創(chuàng)建一個簡單的前端頁面:

<!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 參數以允許訪問被封閉的模塊:

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

如果你是在 IDE 中運行應用程序,可以在 IDE 的運行配置中添加這個參數。

在 Eclipse 中配置 JVM 參數來解決 CGLIB 與 Java 模塊系統兼容性問題,可以按照以下步驟操作:

配置 JVM 參數

  1. 打開 Eclipse 項目屬性
  • 在 Eclipse 中,右鍵點擊你的項目,選擇 Properties(屬性)。
  1. 進入 Run/Debug Settings
  • 在左側面板中,選擇 Run/Debug Settings。

  1. 選擇或創(chuàng)建運行配置

  • 如果已有運行配置,選擇你要修改的配置,然后點擊 Edit(編輯)。

  • 如果沒有,點擊 New Configuration(新建配置),然后選擇 Java Application 或 Spring Boot App,點擊 New(新建)。

  1. 配置 VM Arguments

  • 在 Arguments 標簽頁中,找到 VM arguments 輸入框。在這里你可以添加 JVM 啟動參數。

  • 在 VM arguments 輸入框中,添加如下參數:

    --add-opens java.base/java.lang=ALL-UNNAMED
  • 這個參數允許你訪問 Java 內部 API,解決 CGLIB 在模塊系統中的兼容性問題。

  1. 保存配置

  • 點擊 Apply(應用),然后點擊 Run(運行)以保存并應用你的配置。

運行效果

啟動 Spring Boot 項目后,訪問 http://localhost:8080,頁面上將顯示通過 CGLIB 動態(tài)代理處理后的消息,控制臺中可以看到方法執(zhí)行前后的日志輸出。

總結

本文詳細介紹了如何在 Spring Boot 3.3 中使用 CGLIB 實現動態(tài)代理。通過實際的代碼示例,展示了 CGLIB 在動態(tài)代理中的應用,以及如何在 Spring Boot 項目中集成 CGLIB。我們還演示了如何通過 Thymeleaf 和 Bootstrap 實現一個簡單的前端頁面,以展示代理后的效果。希望通過這篇文章,您能對 CGLIB 動態(tài)代理有一個更深入的理解。

責任編輯:武曉燕 來源: 路條編程
相關推薦

2022-09-01 10:40:29

SpringAOPJDK

2023-12-06 08:23:44

代理模式設計模式

2024-10-17 11:24:04

2021-10-18 12:04:22

Spring BootJava開發(fā)

2021-10-18 10:36:31

Spring Boot插件Jar

2024-10-11 11:46:40

2024-10-30 08:05:01

Spring參數電子簽章

2025-02-27 00:32:35

2022-07-05 14:19:30

Spring接口CGLIB

2024-04-18 09:34:28

Reactor項目異步編程

2024-10-15 10:38:32

2024-01-04 07:42:44

JavaCGLIBJDK

2021-07-14 11:07:56

AOPJDKCglib

2024-08-09 08:46:00

Springjar 包YAML

2022-12-26 07:37:23

Nacos代理模式運用場景、

2012-09-28 10:20:14

IBMdw

2012-09-27 09:47:43

SpringJava面向對象

2017-05-11 21:30:01

Android動態(tài)代理ServiceHook

2025-04-17 03:33:00

SpringSQL動態(tài)查詢

2024-09-04 11:16:44

端口Spring配置類
點贊
收藏

51CTO技術棧公眾號