最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java使用動(dòng)態(tài)代理和反射實(shí)現(xiàn)字段變更跟蹤的方案

 更新時(shí)間:2025年12月19日 09:12:30   作者:Full Stack Developme  
該文章介紹了如何使用Java動(dòng)態(tài)代理和反射技術(shù)來跟蹤記錄對(duì)象字段的變更前和變更后的數(shù)據(jù),文章詳細(xì)講解了創(chuàng)建變更記錄數(shù)據(jù)結(jié)構(gòu)、變更跟蹤處理器、代理工廠,并通過示例展示了如何使用和運(yùn)行這個(gè)代理,需要的朋友可以參考下

下面我將展示如何使用Java動(dòng)態(tài)代理和反射技術(shù)來跟蹤記錄對(duì)象字段的變更前和變更后的數(shù)據(jù)。

實(shí)現(xiàn)方案

我們將創(chuàng)建一個(gè)FieldChangeTracker代理,它能夠:

  1. 在字段被修改前記錄原始值
  2. 在字段被修改后記錄新值
  3. 將所有變更記錄保存在日志中

1. 創(chuàng)建變更記錄數(shù)據(jù)結(jié)構(gòu)

import java.util.Date;

public class FieldChangeRecord {
    private String fieldName;
    private Object oldValue;
    private Object newValue;
    private Date changeTime;
    private String methodName;

    public FieldChangeRecord(String fieldName, Object oldValue, Object newValue, String methodName) {
        this.fieldName = fieldName;
        this.oldValue = oldValue;
        this.newValue = newValue;
        this.changeTime = new Date();
        this.methodName = methodName;
    }

    @Override
    public String toString() {
        return "FieldChangeRecord{" +
                "fieldName='" + fieldName + '\'' +
                ", oldValue=" + oldValue +
                ", newValue=" + newValue +
                ", changeTime=" + changeTime +
                ", methodName='" + methodName + '\'' +
                '}';
    }
}

2. 創(chuàng)建變更跟蹤處理器

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class FieldChangeTracker implements InvocationHandler {
    private final Object target;
    private final List<FieldChangeRecord> changeHistory = new ArrayList<>();

    public FieldChangeTracker(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 只攔截setter方法
        if (method.getName().startsWith("set") && args != null && args.length == 1) {
            // 獲取字段名(從setXxx轉(zhuǎn)換為xxx)
            String fieldName = method.getName().substring(3);
            fieldName = Character.toLowerCase(fieldName.charAt(0)) + fieldName.substring(1);

            try {
                // 獲取字段當(dāng)前值(變更前)
                Field field = target.getClass().getDeclaredField(fieldName);
                field.setAccessible(true);
                Object oldValue = field.get(target);
                
                // 調(diào)用原始方法修改值
                Object result = method.invoke(target, args);
                
                // 獲取字段新值(變更后)
                Object newValue = field.get(target);
                
                // 記錄變更
                changeHistory.add(new FieldChangeRecord(
                    fieldName, oldValue, newValue, method.getName()));
                
                return result;
            } catch (NoSuchFieldException e) {
                // 如果沒有對(duì)應(yīng)字段,直接調(diào)用方法
                return method.invoke(target, args);
            }
        } else {
            // 非setter方法直接調(diào)用
            return method.invoke(target, args);
        }
    }

    public List<FieldChangeRecord> getChangeHistory() {
        return new ArrayList<>(changeHistory);
    }

    public void printChangeHistory() {
        System.out.println("=== Field Change History ===");
        for (FieldChangeRecord record : changeHistory) {
            System.out.println(record);
        }
        System.out.println("===========================");
    }
}

3. 創(chuàng)建代理工廠

import java.lang.reflect.Proxy;

public class TrackingProxyFactory {
    @SuppressWarnings("unchecked")
    public static <T> T createTrackingProxy(T target, Class<T> interfaceType) {
        return (T) Proxy.newProxyInstance(
                interfaceType.getClassLoader(),
                new Class<?>[]{interfaceType},
                new FieldChangeTracker(target));
    }
}

4. 示例使用

public interface User {
    String getName();
    void setName(String name);
    int getAge();
    void setAge(int age);
}

public class UserImpl implements User {
    private String name;
    private int age;

    @Override
    public String getName() {
        return name;
    }

    @Override
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public int getAge() {
        return age;
    }

    @Override
    public void setAge(int age) {
        this.age = age;
    }
}

public class Main {
    public static void main(String[] args) {
        User realUser = new UserImpl();
        User userProxy = TrackingProxyFactory.createTrackingProxy(realUser, User.class);
        
        userProxy.setName("Alice");
        userProxy.setAge(25);
        userProxy.setName("Bob");
        userProxy.setAge(30);
        
        // 獲取變更歷史
        FieldChangeTracker tracker = (FieldChangeTracker) Proxy.getInvocationHandler(userProxy);
        tracker.printChangeHistory();
    }
}

5. 示例輸出

運(yùn)行上面的Main類后,輸出可能如下:

=== Field Change History ===
FieldChangeRecord{fieldName='name', oldValue=null, newValue=Alice, changeTime=..., methodName='setName'}
FieldChangeRecord{fieldName='age', oldValue=0, newValue=25, changeTime=..., methodName='setAge'}
FieldChangeRecord{fieldName='name', oldValue=Alice, newValue=Bob, changeTime=..., methodName='setName'}
FieldChangeRecord{fieldName='age', oldValue=25, newValue=30, changeTime=..., methodName='setAge'}
===========================

高級(jí)改進(jìn)

  1. 支持非接口類:可以使用CGLIB庫來代理沒有接口的類
  2. 線程安全:為changeHistory添加同步控制
  3. 過濾敏感字段:添加注解標(biāo)記不需要跟蹤的字段
  4. 持久化存儲(chǔ):將變更記錄保存到數(shù)據(jù)庫或文件
  5. 性能優(yōu)化:緩存反射獲取的Field對(duì)象

CGLIB版本實(shí)現(xiàn)

如果需要代理沒有實(shí)現(xiàn)接口的類,可以使用CGLIB:

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibTrackingProxyFactory {
    @SuppressWarnings("unchecked")
    public static <T> T createTrackingProxy(T target) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(new CglibFieldChangeTracker(target));
        return (T) enhancer.create();
    }
}

class CglibFieldChangeTracker implements MethodInterceptor {
    private final Object target;
    private final List<FieldChangeRecord> changeHistory = new ArrayList<>();

    public CglibFieldChangeTracker(Object target) {
        this.target = target;
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        // 實(shí)現(xiàn)邏輯與FieldChangeTracker類似
        // ...
    }
    
    // 其他方法與FieldChangeTracker相同
}

這種實(shí)現(xiàn)方式可以跟蹤任何類的字段變更,而不僅限于實(shí)現(xiàn)了接口的類。

到此這篇關(guān)于Java使用動(dòng)態(tài)代理和反射實(shí)現(xiàn)字段變更跟蹤的方案的文章就介紹到這了,更多相關(guān)Java動(dòng)態(tài)代理和反射跟蹤字段變更內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 一步步教你把SpringBoot項(xiàng)目打包成Docker鏡像

    一步步教你把SpringBoot項(xiàng)目打包成Docker鏡像

    Docker可以讓開發(fā)者打包他們的應(yīng)用以及依賴包到一個(gè)輕量級(jí)、可移植的容器中,然后發(fā)布到任何流行的 Linux 機(jī)器上,也可以實(shí)現(xiàn)虛擬化,下面這篇文章主要給大家介紹了關(guān)于SpringBoot項(xiàng)目打包成Docker鏡像的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • java實(shí)現(xiàn)字符串和數(shù)字轉(zhuǎn)換工具

    java實(shí)現(xiàn)字符串和數(shù)字轉(zhuǎn)換工具

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)字符串和數(shù)字轉(zhuǎn)換工具,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-04-04
  • Java多線程(單例模式,阻塞隊(duì)列,定時(shí)器,線程池)詳解

    Java多線程(單例模式,阻塞隊(duì)列,定時(shí)器,線程池)詳解

    本文是多線程初級(jí)入門,主要介紹了多線程單例模式、阻塞隊(duì)列、定時(shí)器、線程池、多線程面試考點(diǎn),感興趣的小伙伴可以跟隨小編一起了解一下
    2022-09-09
  • 使用SpringBoot+EasyExcel+Vue實(shí)現(xiàn)excel表格的導(dǎo)入和導(dǎo)出詳解

    使用SpringBoot+EasyExcel+Vue實(shí)現(xiàn)excel表格的導(dǎo)入和導(dǎo)出詳解

    這篇文章主要介紹了使用SpringBoot+VUE+EasyExcel?整合導(dǎo)入導(dǎo)出數(shù)據(jù)的過程詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08
  • spring cloud學(xué)習(xí)入門之config配置教程

    spring cloud學(xué)習(xí)入門之config配置教程

    這篇文章主要給大家介紹了關(guān)于spring cloud學(xué)習(xí)入門之config配置的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用spring cloud具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-09-09
  • Java 中的語法糖,真甜

    Java 中的語法糖,真甜

    語法糖(Syntactic sugar),也叫做糖衣語法,是英國科學(xué)家發(fā)明的一個(gè)術(shù)語,通常來說使用語法糖能夠增加程序的可讀性,從而減少程序代碼出錯(cuò)的機(jī)會(huì).這篇文章主要介紹了Java 中的語法糖知識(shí),需要的朋友可以參考下
    2020-12-12
  • Java郵件發(fā)送超時(shí)時(shí)間過長問題的優(yōu)化方案

    Java郵件發(fā)送超時(shí)時(shí)間過長問題的優(yōu)化方案

    郵件發(fā)送是許多Java應(yīng)用中常見的功能,尤其在用戶注冊(cè)、密碼重置和系統(tǒng)通知中,對(duì)于一個(gè)高并發(fā)的系統(tǒng)來說,郵件發(fā)送的超時(shí)問題可能導(dǎo)致應(yīng)用性能的下降,甚至影響用戶體驗(yàn),因此,本期我們將討論Java郵件發(fā)送超時(shí)時(shí)間過長 的問題,并深入探討其成因和優(yōu)化策略
    2025-06-06
  • springboot的EnvironmentPostProcessor接口方法源碼解析

    springboot的EnvironmentPostProcessor接口方法源碼解析

    這篇文章主要介紹了springboot的EnvironmentPostProcessor接口方法源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • SpringBoot2.x中management.security.enabled=false無效的解決

    SpringBoot2.x中management.security.enabled=false無效的解決

    這篇文章主要介紹了SpringBoot2.x中management.security.enabled=false無效的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • java 枚舉類定義靜態(tài)valueOf(java.lang.String)方法的問題及解決

    java 枚舉類定義靜態(tài)valueOf(java.lang.String)方法的問題及解決

    這篇文章主要介紹了java 枚舉類定義靜態(tài)valueOf(java.lang.String)方法的問題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09

最新評(píng)論

龙川县| 吐鲁番市| 望奎县| 遂溪县| 建水县| 兴国县| 长宁区| 诸城市| 江阴市| 平阳县| 濉溪县| 任丘市| 怀来县| 乌什县| 平利县| 喜德县| 阜南县| 新竹市| 丁青县| 威信县| 巴南区| 奉化市| 加查县| 黎川县| 岐山县| 密山市| 正安县| 宁晋县| 韶关市| 乌鲁木齐市| 阆中市| 邢台市| 南安市| 邵阳市| 塘沽区| 临邑县| 通海县| 阿克| 瑞金市| 雷波县| 三原县|