欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

如何利用Java?Agent?做Spring?MVC?Controller?層的出參入?yún)⒋蛴∪罩?/h1>
 更新時(shí)間:2024年11月11日 10:40:59   作者:筆墨登場(chǎng)說(shuō)說(shuō)  
本文介紹了如何使用JavaAgent進(jìn)行Spring?MVC?Controller層的出參入?yún)⒋蛴∪罩?首先,建立了一個(gè)包含javassist和fastJSON依賴的Agent?jar工程,并創(chuàng)建了一個(gè)Agent類,然后,編譯并部署了這個(gè)Agent?jar,最后,在Demo?Web工程中啟用Agent以實(shí)現(xiàn)日志打印

許多開(kāi)發(fā)使用的spring aop來(lái)做切面 今天嘗試一下使用JVM層面的切面

1、建立 agent jar工程 

創(chuàng)建工程 logging-agent 使用POM為 javassist 日志

如下:使用了字節(jié)碼 javassist

如果想處理springaop 代理的請(qǐng)?jiān)黾右蕾嚪駝t就不需要

   <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.3.21</version> <!-- 確保使用最新版本 -->
        </dependency>
        <!-- AspectJ Weaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.7</version> <!-- 確保使用最新版本 -->
        </dependency>

為了方便使用fastJSON 做序列化

完整POM如下

<?xml version="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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>logging-agent</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.28.0-GA</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.3.21</version> <!-- 確保使用最新版本 -->
        </dependency>
        <!-- AspectJ Weaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.7</version> <!-- 確保使用最新版本 -->
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version> <!-- 確保使用最新版本 -->
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.4</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer
                                        implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>org.logging.LoggingAgent</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <archive>
                        <!--自動(dòng)添加META-INF/MANIFEST.MF -->
                        <manifest>
                            <addClasspath>true</addClasspath>
                        </manifest>
                        <manifestEntries>
                            <Premain-Class>org.logging.LoggingAgent</Premain-Class>
                            <Agent-Class>org.logging.LoggingAgent</Agent-Class>
                            <Can-Redefine-Classes>true</Can-Redefine-Classes>
                            <Can-Retransform-Classes>true</Can-Retransform-Classes>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2、建立一個(gè)Agent類

package org.logging;
import com.alibaba.fastjson.JSON;
import javassist.*;
import org.springframework.aop.framework.AopProxyUtils;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
import java.util.*;
public class LoggingAgent {
    public static void premain(String agentArgs, Instrumentation inst) {
        inst.addTransformer(new LoggingTransformer());
    }
    static Set<Class<?>> skipLogClassSet = new HashSet<>();
    static Map<Class<?>, Boolean> decisionSkipClassMap = new HashMap<>();
    static {
        skipLogClassSet.add(forName("org.apache.catalina.connector.RequestFacade"));
        skipLogClassSet.add(forName("javax.servlet.ServletRequest"));
        skipLogClassSet.add(forName("javax.servlet.ServletResponse"));
    }
    public static Class<?> forName(String clazz) {
        try {
            return Class.forName(clazz);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return Void.class;
    }
    public static String toJSONString(Object[] a) {
        if (a == null)
            return "null";
        int iMax = a.length - 1;
        if (iMax == -1)
            return "[]";
        StringBuilder b = new StringBuilder();
        b.append('[');
        for (int i = 0; ; i++) {
//            b.append(String.valueOf(a[i]));
            Class<?> clazz = a[i].getClass();
            System.out.println(clazz);
            if (!decisionSkipClassMap.containsKey(clazz)) {
                // 檢查類是否實(shí)現(xiàn)了每個(gè)接口
                for (Class<?> interfaceClass : skipLogClassSet) {
                    if (interfaceClass.isAssignableFrom(clazz)) {
                        System.out.println("myObject 的類實(shí)現(xiàn)了 " + interfaceClass.getName() + " 接口");
                        decisionSkipClassMap.put(clazz, true);
                    } else {
                        System.out.println("myObject 的類沒(méi)有實(shí)現(xiàn) " + interfaceClass.getName() + " 接口");
                        if (decisionSkipClassMap.containsKey(clazz) && decisionSkipClassMap.get(clazz)) {
                            //nothing
                            System.out.println("myObject 的類沒(méi)有實(shí)現(xiàn) " + interfaceClass.getName() + " 接口 但是實(shí)現(xiàn)了其他忽略接口");
                        } else {
                            decisionSkipClassMap.put(clazz, interfaceClass.isAssignableFrom(clazz));
                        }
                    }
                }
            }
            if (!decisionSkipClassMap.get(clazz)) {
                b.append(JSON.toJSONString(a[i]));
            }
            if (i == iMax)
                return b.append(']').toString();
            b.append(", ");
        }
    }
    public static class LoggingTransformer implements ClassFileTransformer {
        @Override
        public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
            // 忽略不需要處理的類
            if (!className.startsWith("com/xdx/interfaces/facade")) {
                return null;
            }
            // Skip Spring CGLIB proxy classes
            if (className.contains("$$EnhancerBySpringCGLIB$$")) {
                return null;
            }
            // Skip Spring CGLIB FastClass proxy classes
            if (className.contains("$$FastClassBySpringCGLIB$$")) {
                return null;
            }
            try {
                String finalClassName = getFinalClassName(className.replace("/", "."));
                ClassPool pool = ClassPool.getDefault();
                pool.insertClassPath(new ClassClassPath(this.getClass()));
                CtClass ctClass = pool.get(finalClassName);
                // 獲取類的所有聲明字段
                CtField[] fields = ctClass.getDeclaredFields();
                String logger = null;
                // 打印字段的名稱和類型
                for (CtField field : fields) {
                    System.out.println("Field Name: " + field.getName() + ", Field Type: " + field.getType().getName());
                    if ("org.slf4j.Logger".equals(field.getType().getName())) {
                        logger = field.getName();
                    }
                }
                for (CtMethod method : ctClass.getDeclaredMethods()) {
                    try {
                        addLogging(method, logger);
                    } catch (Exception e) {
                        System.err.println("Failed to instrument method: " + method.getName());
                        e.printStackTrace();
                    }
                }
                return ctClass.toBytecode();
            } catch (NotFoundException e) {
                // Log exception and continue without instrumentation
                System.err.println("Class not found: " + className + " - " + e.getMessage());
            } catch (Exception e) {
                e.printStackTrace();
            }
            return classfileBuffer;
        }
        private String getFinalClassName(String className) {
            if (className.contains("$$EnhancerBySpringCGLIB$$") || className.contains("$$FastClassBySpringCGLIB$$")) {
                try {
                    Class<?> proxyClass = Class.forName(className);
                    Class<?> targetClass = AopProxyUtils.ultimateTargetClass(proxyClass);
                    return targetClass.getName();
                } catch (ClassNotFoundException e) {
                    // Handle exception and return the original className
                    e.printStackTrace();
                }
            }
            return className;
        }
        private void addLogging(CtMethod method, String logger) throws CannotCompileException {
            if (Objects.isNull(logger)) {
                addLogging2(method);
            } else {
                addLogging1(method, logger);
            }
        }
        private void addLogging1(CtMethod method, String logger) throws CannotCompileException {
//            method.insertBefore("System.out.println(\"[ENTER] Method: " + method.getName() + " Arguments: \" + java.util.Arrays.toString($args));");
            method.insertBefore(logger + ".info(\"[ENTER1] Method: " + method.getName() + " Arguments: \" +org.logging.LoggingAgent.toJSONString($args));");
//            method.insertBefore("log.info(org.logging.LoggingAgent.toJSONString($args));");
            method.insertAfter(logger + ".info(\"[EXIT1] Method: " + method.getName() + " Return: \" + $_);");
//            method.insertBefore(logger + ".info(\"[EXIT] Method: " + method.getName() + " Return: \" + org.logging.LoggingAgent.toJSONString($_));");
        }
        private void addLogging2(CtMethod method) throws CannotCompileException {
            method.insertBefore("org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(this.getClass());"
                    + "logger.info(\"[ENTER2] Method: " + method.getName() + " Arguments: \" +  org.logging.LoggingAgent.toJSONString($args));");
//            method.insertBefore("org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(this.getClass());" +
//                    "logger.info(\"[ENTER] Method: " + method.getName() + " Arguments: \" + java.util.Arrays.toString($args));");
            method.insertAfter(
                    "logger.info(\"[EXIT2] Method: " + method.getName() + " Return: \" + $_);", true);//src:表示插入的代碼,這是一段 Java 源代碼的 String。
//            asFinally:這是一個(gè) boolean 值,決定了插入的代碼塊是在正常返回后執(zhí)行,還是在方法的正常返回和異常返回后都執(zhí)行。
//            method.insertAfter("org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(this.getClass());" +
//                    "logger.info(\"[EXIT] Method: " + method.getName() + " Return: \" + logger.info(org.logging.LoggingAgent.toJSONString($_)));", true);
        }
        private void addLogging3(CtMethod method) throws CannotCompileException {
            method.insertBefore("System.out.println(\"[ENTER] Method: " + method.getName() + " Arguments: \" + java.util.Arrays.toString($args));");
            method.insertAfter("System.out.println(\"[EXIT] Method: " + method.getName() + " Return: \" + $_);");
        }
    }
}

3、打agent jar

4、創(chuàng)建一個(gè)demoWeb工程

-javaagent:D:\code\logging-agent\target\logging-agent-1.0-SNAPSHOT.jar

為了能調(diào)試需要增加jar 

到此這篇關(guān)于利用Java Agent 做Spring MVC Controller 層的出參入?yún)⒋蛴∪罩镜奈恼戮徒榻B到這了,更多相關(guān)Spring MVC Controller 層出參入?yún)⒋蛴∪罩緝?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Gradle修改本地倉(cāng)庫(kù)的位置方法實(shí)現(xiàn)

    Gradle修改本地倉(cāng)庫(kù)的位置方法實(shí)現(xiàn)

    這篇文章主要介紹了Gradle修改本地倉(cāng)庫(kù)的位置方法實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • 基于Java實(shí)現(xiàn)圖形驗(yàn)證碼工具類

    基于Java實(shí)現(xiàn)圖形驗(yàn)證碼工具類

    這篇文章主要為大家詳細(xì)介紹了如何基于Java實(shí)現(xiàn)圖形驗(yàn)證碼工具類,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-11-11
  • Java實(shí)戰(zhàn)小技巧之?dāng)?shù)組與list互轉(zhuǎn)

    Java實(shí)戰(zhàn)小技巧之?dāng)?shù)組與list互轉(zhuǎn)

    在Java中,經(jīng)常遇到需要List與數(shù)組互相轉(zhuǎn)換的場(chǎng)景,下面這篇文章主要給大家介紹了關(guān)于Java實(shí)戰(zhàn)小技巧之?dāng)?shù)組與list互轉(zhuǎn)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-08-08
  • Java多線程案例之阻塞隊(duì)列詳解

    Java多線程案例之阻塞隊(duì)列詳解

    阻塞隊(duì)列是一種特殊的隊(duì)列.?也遵守?“先進(jìn)先出”?的原則.阻塞隊(duì)列能是一種線程安全的數(shù)據(jù)結(jié)構(gòu)。本文將通過(guò)一些示例為大家詳細(xì)講講阻塞隊(duì)列的原理與使用,感興趣的小伙伴可以學(xué)習(xí)一下
    2022-10-10
  • 解決mybatisplus的分頁(yè)插件和條件構(gòu)造器自定義SQL遇到的BUG

    解決mybatisplus的分頁(yè)插件和條件構(gòu)造器自定義SQL遇到的BUG

    這篇文章主要介紹了解決mybatisplus的分頁(yè)插件和條件構(gòu)造器自定義SQL遇到的BUG,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • 詳解IntelliJ IDEA 自定義方法注解模板

    詳解IntelliJ IDEA 自定義方法注解模板

    本篇文章主要介紹了IntelliJ IDEA 自定義方法注解模板,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • 深入解析Spring?Boot?的SPI機(jī)制詳情

    深入解析Spring?Boot?的SPI機(jī)制詳情

    這篇文章主要介紹了深入解析Spring?Boot的SPI機(jī)制詳情,SPI是JDK內(nèi)置的一種服務(wù)提供發(fā)現(xiàn)機(jī)制,可以用來(lái)啟用框架擴(kuò)展和替換組件,主要用于框架中開(kāi)發(fā),更多相關(guān)介紹,感興趣的小伙伴可以參考一下下面文章內(nèi)容
    2022-08-08
  • Java通過(guò)接口實(shí)現(xiàn)匿名類的實(shí)例代碼

    Java通過(guò)接口實(shí)現(xiàn)匿名類的實(shí)例代碼

    這篇文章介紹了Java通過(guò)接口實(shí)現(xiàn)匿名類的實(shí)例代碼,有需要的朋友可以參考一下
    2013-10-10
  • java.text.DecimalFormat類十進(jìn)制格式化

    java.text.DecimalFormat類十進(jìn)制格式化

    這篇文章主要為大家詳細(xì)介紹了java.text.DecimalFormat類十進(jìn)制格式化的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • java 排序算法之快速排序

    java 排序算法之快速排序

    這篇文章主要介紹了java 排序算法之快速排序,文中通過(guò)圖片和代碼講解相關(guān)知識(shí)非常詳細(xì),大家如果有需要的話可以參考一下這篇文章
    2021-09-09

最新評(píng)論