简体   繁体   中英

How to load one of same named resources from different jars in a classpath?

Let's say there is a jar main.jar which depends on two other jars - dep1.jar and dep2.jar . Both dependencies are in a classpath in MANIFEST.MF of main.jar . Each of dependency jars has a directory foo inside with a file bar.txt within:

dep1.jar
|
\--foo/
   |
   \--bar.txt

dep2.jar
|
\--foo/
   |
   \--bar.txt

Here is a main class of main.jar :

public class App
{
    public static void main( String[] args ) {
        ApplicationContext ctx = new StaticApplicationContext();
        Resource barResource = ctx.getResource("classpath:foo/bar.txt");
    }
}

Which of two bar.txt files will be loaded? Is there a way to specify in a resource URL a jar the file should be loaded from?

Flip a quarter, that's the one you'll get. Most likely, it will be the one highest alphabetically, so in your case the one inside dep1.jar. The files both have identical classpaths (foo.Bar), and while this should look to throw a compile time exception, it will not because it will just package both jars up and not try to compile/look at the (this specific file) file as it is a .txt file.

You wouldn't expect a compile time exception as resource loading is a run time process.

You can't specify which jar the resource will come from in code, and this is a common issue, particularly when someone bundles something like log4j.properties into a jar file.

What you can do is specify the order of jars in your classpath, and it will pick up the resource from the first one in the list. This is tricky in itself as when you are using something like ivy or maven for classpath dependencies, you are not in control of the ordering in the classpath (in the eclipse plugins at any rate).

The only reliable solution is to call the resources something different, or put them in separate packages.

Which one you get is undefined. However, you can use

Resource[] barResource = ctx.getResources("classpath*:foo/bar.txt");

to get them both (all). The URL in the Resource will tell you which jar they are in (though I don't recommend you start programming based on that information).

The specification says that the first class/resource on the class path is taken (AFAIK).

However I would try:

Dep1Class.class.getResource("/foo/bar.txt");
Dep2Class.class.getResource("/foo/bar.txt");

As Class.getResource works cannot take resources from another jar, as opposed to the system class loader.

With a bit of luck, you will not need to play with ClassLoader s and hava a different class loader load dep2.jar.

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