zoukankan      html  css  js  c++  java
  • 加载 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/
  • 相关阅读:
    数据结构-队列的链式存储(链队列)
    数据结构-栈的实现之运算式求值
    数据结构-栈的实现之迷宫解密
    Ninject之旅之七:Ninject依赖注入
    Ninject之旅之六:Ninject约定
    Ninject之旅之五:Ninject XML配置
    Ninject之旅之四:Ninject模块
    Ninject之旅之三:Ninject对象生命周期
    Ninject之旅之二:开始使用Ninject(附程序下载)
    Ninject之旅之一:理解DI
  • 原文地址:https://www.cnblogs.com/zno2/p/4692818.html
Copyright © 2011-2022 走看看