158

Documented at 4.7.2.2 The classpath*: prefix it states

This special prefix specifies that all classpath resources that match the given name must be obtained (internally, this essentially happens via a ClassLoader.getResources(...) call), and then merged to form the final application context definition.

Can someone explain this?

What is the difference between using classpath*:conf/appContext.xml as opposed to classpath:conf/appContext.xml without the asterisk.

Manuel Jordan
  • 15,253
  • 21
  • 95
  • 158
JavaRocky
  • 19,203
  • 31
  • 89
  • 110
  • Future readers, also see this bug, with a "status=declined". https://github.com/spring-projects/spring-framework/issues/16017 Just in case the URL ever eventually fails, the title of the bug post is " Import of an XML file from the root of a JAR file with wildcard classpath and wildcard path does not work [SPR-11390] " – granadaCoder Feb 24 '19 at 08:28

4 Answers4

229

SIMPLE DEFINITION

The classpath*:conf/appContext.xml simply means that all appContext.xml files under conf folders in all your jars on the classpath will be picked up and joined into one big application context.

In contrast, classpath:conf/appContext.xml will load only one such file... the first one found on your classpath.

geoand
  • 60,071
  • 24
  • 172
  • 190
Eugene Ryzhikov
  • 17,131
  • 3
  • 38
  • 60
  • 8
    there is one more interesting difference between them. See my question also : http://stackoverflow.com/questions/16985770/runwith-and-contextconfiguration-weird-behaviour – Eugene Jun 08 '13 at 18:48
  • 37
    One very important thing - if you use the * and Spring finds no matches, it will not complain. If you don't use the * and there are no matches, the context will not start up (!) – Roy Truelove Apr 04 '14 at 19:32
43

The classpath*:... syntax is useful primarily when you want to build an application context from multiple bean definition files, using wildcard syntax.

For example, if you construct your context using classpath*:appContext.xml, the classpath will be scanned for every resource called appContext.xml in the classpath, and the bean definitions from all of them merged into a single context.

In contrast, classpath:conf/appContext.xml will obtain one and only one file called appContext.xml from the the classpath. If there is more than one, the others will be ignored.

skaffman
  • 398,947
  • 96
  • 818
  • 769
  • 2
    Will classpath* look in subdirectories too? In other words, if I have appContext.xml in the classpath root and one in /dir/appContext.xml, will it load both when I use classpath*:appContext.xml? – AHungerArtist Sep 22 '15 at 17:17
24

classpath*: It refers to a list of resources and loads all such files present in the classpath and list can be empty and if no such file is present in the classpath then application does not throw any exception (just ignores the error).

classpath: It refers to a certain resource and loads only the first file found on the classpath and if no such file is present in the classpath then it will throw an exception

java.io.FileNotFoundException: 
class path resource [conf/appContext.xml] cannot be opened because it does not exist
Manuel Jordan
  • 15,253
  • 21
  • 95
  • 158
Bacteria
  • 8,406
  • 10
  • 50
  • 67
  • [Official Doc](https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/resources.html) "It's not possible to use the classpath*: prefix to construct an actual `Resource`, as a resource points to just one resource at a time." plus I just got this weird error, that is how I ended up here. If you are going to import resource then it makes no sense to use wildcard classpath prefix. – GabrielOshiro Sep 25 '18 at 21:19
1

The source code of Spring:

public Resource[] getResources(String locationPattern) throws IOException {
   Assert.notNull(locationPattern, "Location pattern must not be null");
   //CLASSPATH_ALL_URL_PREFIX="classpath*:"
   if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
      // a class path resource (multiple resources for same name possible)
      if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
         // a class path resource pattern
         return findPathMatchingResources(locationPattern);
      }
      else {
         // all class path resources with the given name
         return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
      }
   }
   else {
      // Only look for a pattern after a prefix here
      // (to not get fooled by a pattern symbol in a strange prefix).
      int prefixEnd = locationPattern.indexOf(":") + 1;
      if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {
         // a file pattern
         return findPathMatchingResources(locationPattern);
      }
      else {
         // a single resource with the given name
         return new Resource[] {getResourceLoader().getResource(locationPattern)};
      }
   }
}  
zzz
  • 11
  • 1