Java双亲委派机制的妙用
最近在项目中看到一段通过easyexcel导出动态表头的实现,开始我以为是easyexcel官方的实现,其中有这样一段代码:
1 | //将动态表头上传至ThreadLocal |
其中result是通过接口拿到的用户表头配置,我看到有这么个东西:ThreadLocalUtil
,以为是easyexcel的实现,到github查找了一番,结果什么也没有发现。
idea点进去查看了一下,发现是内部的一个实现:
1 | public class ThreadLocalUtil { |
同时还发现了以下几个文件:
一开始我的想法是,这几个文件应该是easyexcel预留的扩展,只需要继承某些父类,重写几个方法就行了。但是这样一来,肯定需要有什么地方配置,类似SPI一样。
于是我通过上面的文件名在项目中查找,结果什么也没有找到。也就是说上面几个文件跟easyexcel并没有产生什么联系。那为什么通过这几个文件就能实现导出动态表头呢?
没办法,只能debug了,这时我发现在easyexcel包中也有一个ExcelHeadProperty
,跟上面说的那个文件并不是同一个。在idea中导航到的是easyexcel中的class,但是实际执行的却不是。
仔细一看,发现这两个文件除了内容不一样,包名是完全一样的:com.alibaba.excel.metadata.property
,这时我想到了Java的双亲委派机制。而项目又并不是直接依赖的easyexcel,是通过间接依赖进来的。
所以被改写过的ExcelHeadProperty 先于easyexcel本身的文件被加载,等到加载easyexcel中的相同class时,发现已经被加载过了。不在加载了。
然后我又在项目中加了一个相同的文件,简单修改了一下,发现项目中的class加载优先级更高,class又一次被改写了:
不得不说,妙啊!