项目中使用了org.springframework.cglib.beans.BeanCopier
进行JavaBean的复制操作,此操作不会进行类型转换操作,及类型不一致时,属性无法赋值,包括基本类型和包装类型,需要使用Converter进行类型转换。
查看Converter时发现没有参数名的描述,于是在github上查询Spring-core的源码,发现源码与Jar中文件差异很大
spring-core.jar
spring-core源码
许多jar中的class文件在源码中不存在,怀疑为打包时进行了某些操作,于是查询spring-core.gradle文件
spring-core 包括 asm 和重新打包 cglib,将两者内联到 spring-core jar 中。
cglib 本身依赖于 asm,因此被 ShadowJar 任务进一步转换为
依赖于 org.springframework.asm; 这避免了包含两个不同的 asm 副本。
由此可见spring-core在打包时,将asm和cglib的包迁移到了自身的jar中,通过gradle的relocate操作
经查询,maven也有相似的功能,通过maven-shade-plugin操作
使用方法:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<relocations>
<relocation>
<!-- 源包名 -->
<pattern>com.google.common</pattern>
<!-- 目的包名 -->
<shadedPattern>org.example.google.common</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
测试
guava 26-jre版本中存在com.google.common.base.Strings.lenientFormat
方法,此方法在guava 19版本中是不存在的
创建3个项目用于测试
- guava19项目,引入guava19版本
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>19.0</version> </dependency>
- guava26项目,引入guava26-jra版本
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>26.0-jre</version> </dependency>
- test-relocation-main项目,引入guava19与guava26项目
<dependency> <groupId>org.example</groupId> <artifactId>guava19</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.example</groupId> <artifactId>guava26</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
在guava19项目中创建一个测试类
public class Guava19Test {
public static void test(){
Objects.toStringHelper(String.class);
}
}
测试该方法,可正确执行
在guava26项目中创建一个测试类
public class Guava26Test {
public static void test(){
Strings.lenientFormat("asd","xxcz");
}
}
测试该方法,可正确执行
在test-relocation-main中执行两个测试方法
public class App {
public static void main(String[] args) {
Guava19Test.test();
Guava26Test.test();
}
}
此时会抛出异常Exception in thread "main" java.lang.NoSuchMethodError: com.google.common.base.Strings.lenientFormat(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
Strings.lenientFormat
方法没有找到
查看maven依赖关系
可见此时test-relocation-main中的guava使用的是19版本
如果排除掉19版本的依赖
<dependency>
<groupId>org.example</groupId>
<artifactId>guava19</artifactId>
<version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.example</groupId>
<artifactId>guava26</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
再去执行测试代码,此时会提示Exception in thread "main" java.lang.NoSuchMethodError: com.google.common.base.Objects.toStringHelper(Ljava/lang/Class;)Lcom/google/common/base/Objects$ToStringHelper;
在guava19的build中添加shade插件
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<relocations>
<relocation>
<!-- 源包名 -->
<pattern>com.google.common</pattern>
<!-- 目的包名 -->
<shadedPattern>org.example.google.common</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
然后执行打包命令 mvn clean install -Dmaven.test.skip=true
执行完成,刷新maven依赖
再去test-relocation-main的测试类中执行测试方法,此时测试可通过
查看依赖的jar,可见我们自己的包中已经将相关的文件复制了过来
参考:
https://www.jianshu.com/p/a3ed849610ad
https://blog.csdn.net/ifenggege/article/details/108327167