Maven项目依赖中getResourceAsStream()加载非自身资源问题咨询
为什么项目A的代码会加载项目B的config.properties?怎么解决?
这事儿我之前在多模块Maven项目里踩过坑,其实核心原因是Java类加载器的资源查找逻辑加上Maven构建后的classpath顺序在搞鬼:
问题根源
- 类加载器的资源查找规则:当你调用
classInA.class.getResourceAsStream("/config.properties")时,这个方法会从classpath的根目录开始查找资源。Java的类加载器会按照classpath中各个路径的先后顺序依次扫描,只要找到第一个匹配文件名的资源,就直接返回它,不会继续往后找。 - Maven的classpath顺序:当你运行项目B时,Maven会把项目B自身编译后的
target/classes目录(也就是B的resources目录编译后的结果)放在classpath的最前面,而依赖的项目A的Jar包则排在后面。所以当A的代码去加载/config.properties时,类加载器先在B的classes目录里找到了同名文件,自然就返回这个,而不会去读A的Jar里的那个了。
解决办法
这里给你几个靠谱的方案,按需选择:
方案1:给A的配置文件重命名(最简单)
直接把A的config.properties改成独一无二的名字,比如a-project-config.properties,然后修改A的代码加载这个新文件名:
InputStream in = classInA.class.getResourceAsStream("/a-project-config.properties");
这种方式完全避免了文件名冲突,不需要折腾类加载器,适合快速解决问题。
方案2:把A的配置文件和类绑定(最可靠)
把A的config.properties放到和classInA同一个包路径下,比如如果classInA在com.example.projecta包下,就把配置文件放在A的resources/com/example/projecta/目录里。然后修改A的代码用相对路径加载:
// 不带开头的斜杠,会从当前类所在的包路径开始查找 InputStream in = classInA.class.getResourceAsStream("config.properties");
这样类加载器会直接去classInA所在的包路径下找配置文件,完全不会和B根目录下的同名文件冲突,是模块化开发中推荐的做法。
方案3:直接指定从A的Jar加载(进阶)
如果不想改文件路径或名字,可以通过URLClassLoader直接定位A的Jar包中的资源。不过这种方式代码稍复杂,而且依赖类加载器的具体实现,示例代码如下:
// 获取A的类所在的Jar包路径 URL jarUrl = classInA.class.getProtectionDomain().getCodeSource().getLocation(); URLClassLoader jarClassLoader = new URLClassLoader(new URL[]{jarUrl}); InputStream in = jarClassLoader.getResourceAsStream("config.properties");
这种方式强制从A的Jar包中加载资源,适合必须保留同名文件的场景,但要注意类加载器的权限问题。
内容的提问来源于stack exchange,提问作者Nicky Buttigieg
相关产品推荐
相关产品推荐

