Maven Shade 插件替换 Calcite Jar 包 class 文件
Maven Shade 插件替换 Calcite Jar 包 class 文件
由于项目中直接通过 Copy Calcite Jar 包内部的 Java 文件的方式进行代码修改,在运行 ShardingSphere Proxy 过程中,ShardingSphere 的 Jar 包和第三方 Jar 包都放在 lib 目录下,类加载器加载类时,可能会随机加载到 calcite 原有 Jar 包里的同名类,导致类覆盖修改失效。
此处使用 Maven Shade Plugin 在打包阶段将项目中自定义的同名类,替换掉 Calcite Jar 包里的类,实现定制代码。
Maven Shade 插件功能
官网介绍了如下几种使用方式:
- 将多个 Jar 包合并成一个 all in one Jar 包
通过 artifactSet 配置要打包哪些 Jar 为一个 all in one Jar:1
2
3
4
5
6
7
8
9
10
11
12<configuration>
<artifactSet>
<includes>
<include>classworlds:classworlds</include>
<include>junit:junit</include>
</includes>
<excludes>
<exclude>jmock:*</exclude>
<exclude>org.apache.maven:lib:tests</exclude>
</excludes>
</artifactSet>
</configuration>
通过 filters 标签配置对指定的 artifact 里的类进行 include 和 exclude 操作:
1 |
|
通过 relocations 标签将包名 shade,避免依赖冲突
1
2
3
4
5
6
7
8
9
10
11<configuration>
<relocations>
<relocation>
<pattern>org.codehaus.plexus.util</pattern>
<shadedPattern>org.shaded.plexus.util</shadedPattern>
<excludes>
<exclude>org.codehaus.plexus.util.xml.pull.*</exclude>
</excludes>
</relocation>
</relocations>
</configuration>通过 transformer 处理 MANIFEST
此处通过 ManifestResourceTransformer 实现类,自定义 Jar 包的 mainClass 启动类。1
2
3
4
5
6
7<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.sonatype.haven.HavenCli</mainClass>
</transformer>
</transformers>
</configuration>
替换 Calcite Jar 包里的类
很显然,要实现项目中定制 Calcite Jar 包里的类,采用第一种方式即可,配置示例如下:
以下配置将 calcite-core 和 federation-compiler 两个 Jar 包 shade 成一个 Jar 包,使用 federation-compiler 类自定义的 calcite 实现类覆盖原有 calcite Jar 包里的实现类,最终打包后的包名仍然使用 calcite-core.jar 实现类覆盖。
1 |
|
需要注意的点,比如原有 Calcite 里 RexCallBinding.java 里具有内部类,最终编译后的 Jar 包里会包含 RexCallBinding.class 和 RexCallBinding$1.class
两个 class 文件,需要同时排除掉,避免后续 Jar 包中的类异常。
替换完毕后,可以用二进制比对工具或者 Java 反编译工具,对比下最终生成所有 class 文件是否符合预期。