编译期动态替换三方包中的Class文件

文章介绍了如何在Java项目中,通过maven-dependency-plugin插件动态替换类文件,从而在不修改源码的情况下,在底层数据添加字段。这种方法利用了类加载器的双亲委派机制,但建议尽量避免使用,以防依赖包升级时的兼容性问题。

背景

最近做业务时遇到一个问题,客户想在底层数据添加一个字段,只能乖乖的添加表字段、实体添加对应属性,一切都在预期中进行这,但是这个工程是经过二开的,展示层实体没法直接添加,于是想当然继承实体扩展字段,没想到顶层一堆Request、Response,如果一个一个进行扩展马也得累死,于是就思考有没有简便的方法仅对目标实体进行操作来完成字段添加的方法。

思考过程

在Java中要在类中添加字段属性,除了显示编码外,还有一种技术就是编译期间动态修改,比如Lombok、Mapstruct等都是在编译期动态生成代码,提高编码效率,所以我也考虑通过这种方式编译期添加目标字段属性,百度了一通没有合适的方式动态添加,但是手写通过字节码注入一定是可以实现的,想想成本还是有点高,赶紧转换思路,既然不能动态插入字段,那能不能直接替换目标类呢?一想到这就有戏,在Java中加载类是通过类加载器进行加载的,有了依据后赶紧接着百度,果不然让我发现一种方式,通过maven插件的方式实现,客官接着往下看。

一般情况下不建议用这么hack的方式哈,尽量保持三方包的新鲜度,避免未来升级导致的兼容性问题。

主角出场

主角:maven-dependency-plugin

这仅仅是处理的一种方式,大家如果有更好的处理方式,可以放到评论区,我们一起讨论,互相学习进步。

实现原理

通过配置maven-dependency-plugin, 可以将我们指定的dependency解压到项目的class目录中,设置不覆盖本地项目相同class文件(类的全限定名相同),就实现了本地文件替换三方jar中类文件的目的了。

在Java应用中,如果存在多个同名类,最终只会加载一个目标类,到底会加载哪个同名类是又类加载器的双亲委派机制决定的,先请求父类加载器加载,父类无法加载回到应用程序加载器,应用程序无法加载就会到类路径下即class目录中加载,如果仍然不存在会到依赖中进行加载。

基于以上原理,实现类文件覆盖就有了依据,那么接下来具体实践演示下。

使用

这里我使用commons-lang3举例。

第一步:配置Maven插件

<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-dependency-plugin</artifactId><version>3.1.2</version><executions><execution><!-- unpack任务标识符,unpack是将依赖从仓库中解压到指定目录 --><id>unpack</id><!-- unpack任务默认执行阶段 --><phase>generate-sources</phase><goals><!-- 目标功能:unpack --><goal>unpack</goal></goals><configuration><artifactItems><artifactItem><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><!-- 设置为false,依赖解压到目录时不会进行覆盖,设置为true则会覆盖 --><overWrite>false</overWrite><!-- 目标class文件输出目录 --><outputDirectory>${project.build.directory}/classes</outputDirectory></artifactItem></artifactItems></configuration></execution></executions></plugin>复制代码

第二步:编译工程

这一步还没有定义目标类,暂时仅是将目标三方包的类放到了class目录下,标红的位置是即将要进行修改的位置。

第三步:添加目标类

  • 包名和目标类所在包名完全一致;

  • 类名保持一致;

第四步:重新编译工程

至此已经能够看到效果了,整个方式过程也比较简单,去掉中间的编译过程,总共两步。

总结

这种Hack的方式在业务编码中建议少用,通过上边的方式虽然能解决问题,但同时也引入了一些副作用,一方面相当于依赖包引入两份,另一方面当依赖包升级时可能存在疏漏。看看学习学习,多一种解决方式多一条路,希望大家每天编码顺顺利,我就先溜了!

作者:红兔哥

链接:https://juejin.cn/post/7210369671664959543

<think>首先,用户的问题是:“我想修改HAP中的JSON文件内容 请问如何修改HAP中的文件中的JSON文件值”。这涉及到OpenHarmony开发中的HAP修改。 从系统级指令中,我需要: - 所有行内数学表达式用$...$格式。 - 独立公式用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,如[^1]。 用户提供的引用是:[^1]鸿蒙OH实战开发:在OpenHarmony开发板上验证hap中集成的C/C++三方库... 这描述了在开发板上获取文件路径的方式,但用户的问题是关于修改HAP中的JSON文件内容。 用户的问题不是数学相关的,所以可能不需要数学表达式,但如果有数学部分,我必须遵守格式。例如,如果有变量或路径表达式,我应该用$...$。 回答结构要清晰,帮助用户逐步解决问题,保证真实可靠。 关键点: - HAP是HarmonyOS Ability Package,含应用的资源和代码。 - 修改HAP中的文件,特别是JSON文件,通常需要在开发过程中修改源代码,然后重新打HAP。 步骤: 1. **理解HAP结构**:HAP是一个压缩文件含assets、resources、config.json等文件。 2. **修改JSON文件**:用户想修改JSON文件的值,比如config.json或其他自定义JSON文件。 3. **方法**: - 在开发阶段:修改源代码中的JSON文件,然后重新编译和打HAP。 - 在运行时:如果应用已经安装,可能需要通过文件操作API修改文件,但HAP本身是只读的;通常修改应用数据目录下的文件。 从引用[^1]中,它提到在开发板上获取文件路径:'this.dir = globalThis.abilityContext.filesDir + “/”',对应路径为'/data/app/.../files'。这表明在运行时,应用可以访问自己的数据目录,但HAP是安装,位于不同路径。 在OpenHarmony中: - HAP安装后,其资源文件是只读的。config.json是应用配置,不能运行时修改。 - 对于自定义JSON文件,如果放在assets或resources中,也是只读的。用户数据应存储在内部存储中,如filesDir。 所以,回答应该: 1. 解释HAP的结构。 2. 说明如何修改JSON文件: - 开发时:修改文件,重新打。 - 运行时:如果JSON文件是用户数据,存储在应用目录下,通过文件API修改。 3. 提供代码示例。 用户说“修改HAP中的文件”,但HAP本身是安装修改它可能需要重新打。可能用户指的是修改应用中的JSON文件内容。 生成相关问题:在回答后添加相关问题。 回答结构: - 引言:解释问题。 - 步骤:逐步指导。 - 代码示例:用中文注释。 - 引用:如果适用,添加引用标识。 - 相关问题。 确保LaTeX正确:如果有数学,如路径表达式,用$...$,但可能不需要。 例如,路径可以用行内代码块或$...$表示,但LaTeX是数学,所以最好用代码块。 指令说“所有行内数学表达式(括变量、不等式、方程等)必须使用$...$格式”,但路径不是数学,所以应该用普通文本或代码块。 在引用中,它使用了代码块。 在回答中,使用代码块表示路径和代码。 最终回答: - 用中文。 - 清晰结构。 - 生成相关问题。</think>### 修改HAP中的JSON文件内容 在OpenHarmony开发中,HAP(HarmonyOS Ability Package)是应用的安装含资源文件、配置文件和代码。修改HAP中的JSON文件(如 `config.json` 或其他自定义JSON文件)需要分情况处理,因为HAP本身在安装后是**只读**的。您不能直接修改已安装的HAP文件,但可以通过以下方法实现JSON内容修改: 1. **开发阶段修改(推荐)**: 在源代码中修改JSON文件,然后重新编译和打HAP。这是标准做法,适用于应用发布前的配置调整。 - **步骤**: 1. 在您的OpenHarmony工程中,找到JSON文件的位置(通常位于 `resources/base/element` 或 `assets` 目录下)。 2. 直接编辑JSON文件(例如,使用文本编辑器或IDE修改值)。 3. 重新编译工程:运行 `build` 命令(如使用DevEco Studio的Gradle任务)。 4. 重新生成HAP编译后,HAP会自动更新,您可以在 `build/outputs` 目录下获取新。 - **示例代码**(修改JSON文件并读取): 如果您需要在运行时验证修改,可以使用文件API读取JSON内容。但注意,开发阶段的修改是静态的,需重新打。 ```javascript // 在Ability中读取JSON文件(示例:assets目录下的config.json) import fs from '@ohos.file.fs'; import util from '@ohos.util'; export default { onWindowStageCreate(windowStage) { // 获取assets目录路径(HAP安装后,assets是只读的) let context = getContext(this); let assetPath = context.resourceManager.getRawFileContentSync('entry/resources/base/assets/config.json'); // 解析JSON内容(开发时修改后,这里会读取新值) let jsonText = String.fromCharCode.apply(null, new Uint8Array(assetPath)); let jsonObj = JSON.parse(jsonText); console.log("JSON值: " + jsonObj.key); // 输出修改后的值 } } ``` 在开发时,直接修改 `config.json` 文件并重新打即可生效。 2. **运行时修改(仅限应用数据目录)**: 如果JSON文件是**用户数据**(非HAP内置资源),您可以将其存储在应用的可写目录(如 `filesDir`)中,然后在运行时通过文件API修改。HAP内置文件(如 `assets` 或 `resources`)是只读的,无法直接修改。 - **步骤**: 1. **初始部署**:将JSON文件从HAP复制到应用数据目录(首次运行时)。 2. **修改内容**:使用文件API读写和更新JSON文件。 3. **路径获取**:通过 `abilityContext` 获取可写目录路径,如引用中所述[^1]。 - **示例代码**(运行时修改JSON文件): 以下代码演示如何复制内置JSON到可写目录,并修改其值: ```javascript import fs from '@ohos.file.fs'; import util from '@ohos.util'; export default { async modifyJson() { let context = getContext(this); // 获取应用可写目录路径(如 /data/app/.../files) let filesDir = context.filesDir; let targetPath = filesDir + '/config.json'; // 目标文件路径 // Step 1: 从assets复制JSON到可写目录(首次运行) let assetPath = context.resourceManager.getRawFileContentSync('entry/resources/base/assets/config.json'); await fs.copyFile(assetPath, targetPath); // 复制文件 // Step 2: 读取并修改JSON值 let file = fs.openSync(targetPath, fs.OpenMode.READ_WRITE); let content = fs.readSync(file.fd, new ArrayBuffer(1024)); let jsonText = String.fromCharCode.apply(null, new Uint8Array(content.buffer)); let jsonObj = JSON.parse(jsonText); jsonObj.key = "newValue"; // 修改JSON值 // Step 3: 写回文件 let newContent = JSON.stringify(jsonObj); fs.writeSync(file.fd, newContent); fs.closeSync(file); console.log("JSON修改成功,路径: " + targetPath); } } ``` - **关键点**: - 路径获取:`filesDir` 对应开发板上的绝对路径,如 `/data/app/el2/100/base/com.example.app/haps/entry/files`,这是可写的[^1]。 - 只读限制:HAP内置文件(如 `assets/config.json`)不能直接修改,必须先复制到可写目录。 - 权限:确保在 `config.json` 中声明文件操作权限(如 `ohos.permission.FILE_ACCESS`)。 3. **注意事项**: - **安全性和稳定性**:直接修改HAP文件可能导致应用签名失效或安装失败。始终优先在开发阶段修改。 - **性能**:运行时修改适用于动态配置(如用户设置),但频繁文件I/O可能影响性能。 - **调试**:在开发板上验证时,使用 `hdc` 工具查看文件内容(如 `hdc shell cat /data/app/.../files/config.json`)。 如果JSON文件是核心配置文件(如 `config.json`),修改后可能需要重启应用或设备。建议参考OpenHarmony官方文档:[应用结构](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/quick-start/package-structure.md)。 ### 相关问题 1. 如何在OpenHarmony运行时动态更新应用配置? 2. HAP中的资源文件如何访问和修改? 3. 如何确保JSON文件修改后的应用兼容性?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值