加载 bean*.xml

入口

ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:bean*.xml");

    /**
         * Main entry point.
         * @return {@code true} if the string matches against the pattern, or {@code false} otherwise.
         */
        public boolean matchStrings(String str, Map<String, String> uriTemplateVariables) {
            Matcher matcher = this.pattern.matcher(str);
            if (matcher.matches()) {
                if (uriTemplateVariables != null) {
                    // SPR-8455
                    Assert.isTrue(this.variableNames.size() == matcher.groupCount(),
                            "The number of capturing groups in the pattern segment " + this.pattern +
                            " does not match the number of URI template variables it defines, which can occur if " +
                            " capturing groups are used in a URI template regex. Use non-capturing groups instead.");
                    for (int i = 1; i <= matcher.groupCount(); i++) {
                        String name = this.variableNames.get(i - 1);
                        String value = matcher.group(i);
                        uriTemplateVariables.put(name, value);
                    }
                }
                return true;
            }
            else {
                return false;
            }
        }
    }

最后发现 java.util.regex.Pattern 调用matches() 方法

从而得知 支持正则表达式。

总结:

classpath:bean*.xml
冒号前半部分是为了获取 classpath 文件路径,然后file.lists() 递归循环获取所有 文件路径 ,逐一与冒号后面的 pattern 匹配。


冒号分析

/**
 * A {@link ResourcePatternResolver} implementation that is able to resolve a
 * specified resource location path into one or more matching Resources.
 * The source path may be a simple path which has a one-to-one mapping to a
 * target {@link org.springframework.core.io.Resource}, or alternatively
 * may contain the special "{@code classpath*:}" prefix and/or
 * internal Ant-style regular expressions (matched using Spring's
 * {@link org.springframework.util.AntPathMatcher} utility).
 * Both of the latter are effectively wildcards.
 *
 * <p><b>No Wildcards:</b>
 *
 * <p>In the simple case, if the specified location path does not start with the
 * {@code "classpath*:}" prefix, and does not contain a PathMatcher pattern,
 * this resolver will simply return a single resource via a
 * {@code getResource()} call on the underlying {@code ResourceLoader}.
 * Examples are real URLs such as "{@code file:C:/context.xml}", pseudo-URLs
 * such as "{@code classpath:/context.xml}", and simple unprefixed paths
 * such as "{@code /WEB-INF/context.xml}". The latter will resolve in a
 * fashion specific to the underlying {@code ResourceLoader} (e.g.
 * {@code ServletContextResource} for a {@code WebApplicationContext}).
 *
 * <p><b>Ant-style Patterns:</b>
 *
 * <p>When the path location contains an Ant-style pattern, e.g.:
 * <pre class="code">
 * /WEB-INF/*-context.xml
 * com/mycompany/**&#47;applicationContext.xml
 * file:C:/some/path/*-context.xml
 * classpath:com/mycompany/**&#47;applicationContext.xml</pre>
 * the resolver follows a more complex but defined procedure to try to resolve
 * the wildcard. It produces a {@code Resource} for the path up to the last
 * non-wildcard segment and obtains a {@code URL} from it. If this URL is
 * not a "{@code jar:}" URL or container-specific variant (e.g.
 * "{@code zip:}" in WebLogic, "{@code wsjar}" in WebSphere", etc.),
 * then a {@code java.io.File} is obtained from it, and used to resolve the
 * wildcard by walking the filesystem. In the case of a jar URL, the resolver
 * either gets a {@code java.net.JarURLConnection} from it, or manually parses
 * the jar URL, and then traverses the contents of the jar file, to resolve the
 * wildcards.
 *
 * <p><b>Implications on portability:</b>
 *
 * <p>If the specified path is already a file URL (either explicitly, or
 * implicitly because the base {@code ResourceLoader} is a filesystem one,
 * then wildcarding is guaranteed to work in a completely portable fashion.
 *
 * <p>If the specified path is a classpath location, then the resolver must
 * obtain the last non-wildcard path segment URL via a
 * {@code Classloader.getResource()} call. Since this is just a
 * node of the path (not the file at the end) it is actually undefined
 * (in the ClassLoader Javadocs) exactly what sort of a URL is returned in
 * this case. In practice, it is usually a {@code java.io.File} representing
 * the directory, where the classpath resource resolves to a filesystem
 * location, or a jar URL of some sort, where the classpath resource resolves
 * to a jar location. Still, there is a portability concern on this operation.
 *
 * <p>If a jar URL is obtained for the last non-wildcard segment, the resolver
 * must be able to get a {@code java.net.JarURLConnection} from it, or
 * manually parse the jar URL, to be able to walk the contents of the jar,
 * and resolve the wildcard. This will work in most environments, but will
 * fail in others, and it is strongly recommended that the wildcard
 * resolution of resources coming from jars be thoroughly tested in your
 * specific environment before you rely on it.
 *
 * <p><b>{@code classpath*:} Prefix:</b>
 *
 * <p>There is special support for retrieving multiple class path resources with
 * the same name, via the "{@code classpath*:}" prefix. For example,
 * "{@code classpath*:META-INF/beans.xml}" will find all "beans.xml"
 * files in the class path, be it in "classes" directories or in JAR files.
 * This is particularly useful for autodetecting config files of the same name
 * at the same location within each jar file. Internally, this happens via a
 * {@code ClassLoader.getResources()} call, and is completely portable.
 *
 * <p>The "classpath*:" prefix can also be combined with a PathMatcher pattern in
 * the rest of the location path, for example "classpath*:META-INF/*-beans.xml".
 * In this case, the resolution strategy is fairly simple: a
 * {@code ClassLoader.getResources()} call is used on the last non-wildcard
 * path segment to get all the matching resources in the class loader hierarchy,
 * and then off each resource the same PathMatcher resolution strategy described
 * above is used for the wildcard subpath.
 *
 * <p><b>Other notes:</b>
 *
 * <p><b>WARNING:</b> Note that "{@code classpath*:}" when combined with
 * Ant-style patterns will only work reliably with at least one root directory
 * before the pattern starts, unless the actual target files reside in the file
 * system. This means that a pattern like "{@code classpath*:*.xml}" will
 * <i>not</i> retrieve files from the root of jar files but rather only from the
 * root of expanded directories. This originates from a limitation in the JDK's
 * {@code ClassLoader.getResources()} method which only returns file system
 * locations for a passed-in empty String (indicating potential roots to search).
 *
 * <p><b>WARNING:</b> Ant-style patterns with "classpath:" resources are not
 * guaranteed to find matching resources if the root package to search is available
 * in multiple class path locations. This is because a resource such as
 * <pre class="code">
 *     com/mycompany/package1/service-context.xml
 * </pre>
 * may be in only one location, but when a path such as
 * <pre class="code">
 *     classpath:com/mycompany/**&#47;service-context.xml
 * </pre>
 * is used to try to resolve it, the resolver will work off the (first) URL
 * returned by {@code getResource("com/mycompany");}. If this base package
 * node exists in multiple classloader locations, the actual end resource may
 * not be underneath. Therefore, preferably, use "{@code classpath*:}" with the same
 * Ant-style pattern in such a case, which will search <i>all</i> class path
 * locations that contain the root package.
 *
 * @author Juergen Hoeller
 * @author Colin Sampaleanu
 * @author Marius Bogoevici
 * @author Costin Leau
 * @since 1.0.2
 * @see #CLASSPATH_ALL_URL_PREFIX
 * @see org.springframework.util.AntPathMatcher
 * @see org.springframework.core.io.ResourceLoader#getResource(String)
 * @see ClassLoader#getResources(String)
 */
public class PathMatchingResourcePatternResolver implements ResourcePatternResolver
View Code

PathMatchingResourcePatternResolver 的部分方法↓

 1   @Override
 2     public Resource[] getResources(String locationPattern) throws IOException {
 3         Assert.notNull(locationPattern, "Location pattern must not be null");
 4         if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
 5             // a class path resource (multiple resources for same name possible)
 6             if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
 7                 // a class path resource pattern
 8                 return findPathMatchingResources(locationPattern);
 9             }
10             else {
11                 // all class path resources with the given name
12                 return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
13             }
14         }
15         else {
16             // Only look for a pattern after a prefix here
17             // (to not get fooled by a pattern symbol in a strange prefix).
18             int prefixEnd = locationPattern.indexOf(":") + 1;
19             if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {
20                 // a file pattern
21                 return findPathMatchingResources(locationPattern);
22             }
23             else {
24                 // a single resource with the given name
25                 return new Resource[] {getResourceLoader().getResource(locationPattern)};
26             }
27         }
28     }

locationPattern 的两次值分别是:

  1. classpath:bean*.xml
  2. classpath:

第8行↑ 调用的方法参数是1,在该方法中再一次调用getResources,然后传的参数是2 (目的是为了获取rootDirResources)

第一个if else 是区分classpath*: 这是固定写法↓ ,然后回处理冒号左右↑

  /**
     * Pseudo URL prefix for all matching resources from the class path: "classpath*:"
     * This differs from ResourceLoader's classpath URL prefix in that it
     * retrieves all matching resources for a given name (e.g. "/beans.xml"),
     * for example in the root of all deployed JAR files.
     * @see org.springframework.core.io.ResourceLoader#CLASSPATH_URL_PREFIX
     */
    String CLASSPATH_ALL_URL_PREFIX = "classpath*:";

如果是classpath: 这是固定写法↓ ,则处理冒号左右

  /** Pseudo URL prefix for loading from the class path: "classpath:" */
    String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;

如果是冒号右边是路径,则处理这个资源。↑

如果是冒号右边不是路径,则继续处理。↑【25行】——如下:

 1   @Override
 2     public Resource getResource(String location) {
 3         Assert.notNull(location, "Location must not be null");
 4         if (location.startsWith("/")) {
 5             return getResourceByPath(location);
 6         }
 7         else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
 8             return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
 9         }
10         else {
11             try {
12                 // Try to parse the location as a URL...
13                 URL url = new URL(location);
14                 return new UrlResource(url);
15             }
16             catch (MalformedURLException ex) {
17                 // No URL -> resolve as resource path.
18                 return getResourceByPath(location);
19             }
20         }
21     }

第7行,必须以classpath: 开始。↑

第8行,new ClassPathResource 的实例,其中第一个参数path为"" ,第二个参数为getClassLoader() 返回的实例。↑

 1   protected URL resolveURL() {
 2         if (this.clazz != null) {
 3             return this.clazz.getResource(this.path);
 4         }
 5         else if (this.classLoader != null) {
 6             return this.classLoader.getResource(this.path);
 7         }
 8         else {
 9             return ClassLoader.getSystemResource(this.path);
10         }
11     }

第6行 ,返回了类路径。↑   结果如下:↓

file:/E:/e/workspace/context/target/classes/
原文地址:https://www.cnblogs.com/zno2/p/4692818.html