类加载器如何查找资源?

时间:2015-04-01 04:07:04

标签: java dependency-injection

我正在审查一个小型的github示例项目(shagie/TestingWithHsqldb)并偶然发现了一个对我来说不熟悉的约定,希望有人可以帮助我理解我正在看的内容。


该项目是在主src目录下组织的......

src/main/resources/connection_config.properties
src/main/java/com/shagie/dbtest/db/DBConnection.java
src/main/java/com/shagie/dbtest/db/DataAccess.java

src/test/resources/connection_config.properties
src/test/java/com/shagie/dbtest/db/DataAccessTest.java

DBConnection.java中的代码既可以从'main'目录下的DataAccess.java以及'test'目录中的DataAccessTest.java进行调用。

在文件DBConnection.java中,有以下语句导入connection_config.properties文件:

Properties prop = new Properties();
InputStream in = GetClass().getResourceAsStream("/connection_config.properties");
prop.load(in);
in.close();

我的问题......

  • 如果调用的结构为getResourceAsStream("/connection_config.properties"),那么如何在“resources”目录中找到属性文件?该路径是否意味着它应该查看属性文件的根目录(主要或测试)?

  • 由于DBConnection.java没有更改它的根'main'目录,因此在执行DataAccessTest.java

    时,属性文件是如何来自'test'目录的? LI>
  • 我认为这种模式与依赖注入和单元测试有关。这个特定模式有名称吗?在哪里可以了解更多信息?

编辑:调整问题以关注ClassLoader的{​​{1}}功能而不是依赖注入

1 个答案:

答案 0 :(得分:1)

这与依赖注入无关,而是ClassLoader如何解析资源路径。

1)这可能有点令人困惑,来自Linux背景确实getResourceAsStream(resource)有不同的规则。根据{{​​3}}:

  

如果名称以'/'('\ u002f')开头,则绝对名称为   资源是'/'后面的名称部分。

所以这里的前导斜杠只告诉类加载器如何获取绝对名称(你传递的名字是否应该以包名前缀),而不是它应该是“在根”(在测试/主文件夹)。什么是根和解决方案的工作方式取决于您使用的类加载器。默认情况下(在本例中)在resources文件夹中搜索资源。您可以编写自己的ClassLoader并更改该行为。

2)同样,当调用getResources()getResourceAsStream()时,该类会将其委托给加载此类的ClassLoader。如果您正在运行单元测试(Junit或类似的东西),那么ClassLoader将知道它应该在test文件夹而不是main中查找资源。