简体   繁体   中英

How does the classloader find resources?

I am reviewing a small github example project ( shagie/TestingWithHsqldb ) and have stumbled across a convention that is new to me and was hoping someone could help me understand what I am looking at.


The project is organized under the main src directory as such...

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

The code in DBConnection.java is called both from DataAccess.java under the 'main' directory as well as the DataAccessTest.java in the 'test' directory.

In the file DBConnection.java there is the following statement that imports the connection_config.properties file:

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

My Questions...

  • How is the properties file being found in the "resources" directory if the call is structured as getResourceAsStream("/connection_config.properties") ? Doesn't that path mean it should look at the root directory (main or test) for the properties file?

  • Since DBConnection.java doesn't change it's root 'main' directory, how is it that the properties file comes from the 'test' directory when executing DataAccessTest.java

  • I assume this pattern is related to dependency injection and unit testing. Is there a name for this specific pattern? Where is a good place to learn more about it?

EDIT: Adjusting question to focus on the ClassLoader 's getResource functionality instead of dependency injection

This has nothing to do with dependency injection but with how ClassLoader s resolve resource paths.

1) This might be a bit confusing coming from a Linux background indeed getResourceAsStream(resource) has different rules. As per the doc :

If the name begins with a '/' ('\/'), then the absolute name of the resource is the portion of the name following the '/'.

So the leading slash here only tells the class loader how to get the absolute name (whether the name you passed should be prepended with the package name or not), not that it should be looking "at the root" (in the test/main folders). What is the root and how resolution works depends on the class loader you are using. By default (in this case) resources are searched in the resources folder. You can write your own ClassLoader and change that behavior.

2) Again, when calling getResources() or getResourceAsStream() the class delegates it to the ClassLoader which loaded this class. If you are running unit tests (Junit or something similar) then the ClassLoader will know that it's supposed to look for resources in test folder not main .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM