本文介绍在如何不修改jar包源码的情况下替换jar包中方法的逻辑

很多小伙伴可能会遇到这样的问题,就是在使用jar包的时候,jar包中的某个方法的逻辑不符合自己的业务需求,但是又不想修改jar包源码, 这个时候就需要使用到一些手段了,本文介绍的是利用双亲委派模型来实现逻辑的替换。

修改方法

在项目目录下,根据实际想要覆盖逻辑的类,创建一个相同包名,相同类名的类,然后在类中写入自己想要的逻辑,这样就可以覆盖jar包中的逻辑了。

一般修改可能只会修改某个方法或其中部分逻辑,可以通过反编译查看反编译后的源码,将源码拷贝过来,然后修改即可。

例如在使用java发送邮件的坑一文中,修改Hutool库中Mail类就是使用的此种方式。

注意

  1. 这种方法虽然方便,但可能会导致不可预见的问题,特别是当jar包版本升级后。
  2. 要确保你完全理解要替换的类的逻辑和依赖关系。

基础知识

  1. 类加载器(ClassLoader):在Java中,类是由类加载器动态加载到JVM中的。
  2. 双亲委派模型(Parent-First Delegation Model):这是Java的类加载机制的一个重要特点。简单来说,当一个类加载器需要加载一个类时,它首先会将这个任务委托给其父加载器。这个过程会一直递归下去,直到Bootstrap ClassLoader。

类加载顺序

  1. Bootstrap ClassLoader:加载Java核心库,通常位于$JAVA_HOME/jre/lib。
  2. Extension ClassLoader:加载扩展库,通常位于$JAVA_HOME/jre/lib/ext。
  3. Application ClassLoader:加载应用级别的类库,即在你的项目或应用的classpath中定义的库。

覆盖机制

  1. 当一个类需要被加载时,Application ClassLoader会首先查找项目的编译输出目录(通常是target/classes或out/production/classes)。
  2. 如果在项目编译输出目录中找到了该类,那么这个类就会被加载,而jar包中的同名类不会被加载。
  3. 如果在项目编译输出目录中没有找到该类,类加载器会继续在classpath上其他位置(如jar包)查找。

实际应用

  1. 通过在项目中提供一个与jar包中全限定名(包名+类名)相同的类,你可以利用Java的类加载机制“覆盖”或替换jar包中的类。这个项目中的类会被优先加载和使用,从而达到修改或替换原有逻辑的目的。