编译期动态替换三方包中的Class文件过程详解

 更新时间:2023年03月27日 16:19:44   作者:红兔哥  
这篇文章主要为大家介绍了编译期动态替换三方包中的Class文件过程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

背景

最近做业务时遇到一个问题,客户想在底层数据添加一个字段,只能乖乖的添加表字段、实体添加对应属性,一切都在预期中进行这,但是这个工程是经过二开的,展示层实体没法直接添加,于是想当然继承实体扩展字段,没想到顶层一堆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的方式在业务编码中建议少用,通过上边的方式虽然能解决问题,但同时也引入了一些副作用,一方面相当于依赖包引入两份,另一方面当依赖包升级时可能存在疏漏。看看学习学习,多一种解决方式多一条路,希望大家每天编码顺顺利,我就先溜了!

以上就是编译期动态替换三方包中的Class文件过程详解的详细内容,更多关于编译期动态替换Class文件的资料请关注脚本之家其它相关文章!

相关文章

  • java实现窗口刷新的示例代码

    java实现窗口刷新的示例代码

    本文主要介绍了java实现窗口刷新的示例代码,通过重写paintComponent()方法和调用repaint()方法,可以实现窗口的即时刷新,具有一定的参考价值,感兴趣的可以了解一下
    2024-02-02
  • Java8实现对List<Integer>的求和

    Java8实现对List<Integer>的求和

    这篇文章主要介绍了Java8实现对List<Integer>的求和方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • Java方法重载Overload原理及使用解析

    Java方法重载Overload原理及使用解析

    这篇文章主要介绍了Java方法重载Overload原理及使用解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • mac下修改idea的jvm运行参数解决idea卡顿的情况

    mac下修改idea的jvm运行参数解决idea卡顿的情况

    这篇文章主要介绍了mac下修改idea的jvm运行参数解决idea卡顿的情况,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • mybatis-plus中更新null值的问题解决

    mybatis-plus中更新null值的问题解决

    本文主要介绍 mybatis-plus 中常使用的 update 相关方法的区别,以及更新 null 的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-04-04
  • SpringBoot整合Swagger2的步骤详解

    SpringBoot整合Swagger2的步骤详解

    这篇文章主要介绍了SpringBoot整合Swagger2的步骤详解,帮助大家更好的理解和学习使用SpringBoot框架,感兴趣的朋友可以了解下
    2021-04-04
  • 解决@Transaction注解导致动态切换更改数据库失效问题

    解决@Transaction注解导致动态切换更改数据库失效问题

    这篇文章主要介绍了解决@Transaction注解导致动态切换更改数据库失效问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • Java实现输出数字三角形实例代码

    Java实现输出数字三角形实例代码

    大家好,本篇文章主要讲的是Java实现输出三角形实例代码,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2022-01-01
  • Spring Boot线程池使用的一些实用心得

    Spring Boot线程池使用的一些实用心得

    理论上线程越多程序可能更快,但在实际使用中我们需要考虑到线程本身的创建以及销毁的资源消耗,以及保护操作系统本身的目的我们通常需要将线程限制在一定的范围之类,这篇文章主要给大家介绍了关于Spring Boot线程池使用的一些实用心得,需要的朋友可以参考下
    2021-09-09
  • servlet的url-pattern匹配规则详细描述(小结)

    servlet的url-pattern匹配规则详细描述(小结)

    在利用servlet或Filter进行url请求的匹配时,很关键的一点就是匹配规则。这篇文章主要介绍了servlet的url-pattern匹配规则详细描述(小结),非常具有实用价值,需要的朋友可以参考下
    2018-07-07

最新评论