Spring如何扫描class和配置文件

前几天由于公司项目架构调整,想将以前代码开发为主改成配置文件配置为主,即所有的外部服务调用由配置文件组织,因为必须高效,所以涉及包括调用顺序,并发调用等,但配置文件的缺陷是只能实现简单的业务逻辑,所以我们还用了jeval表达式Jar包。

       废话不多说,由于服务配置文件是放在Maven项目下的一个子模块的classpath下,该子模块在eclipse下运行是以用文件系统路径来扫描到并解析的,但在线上环境,该子模块是会被打成Jar包,就是说线上环境是需要解析该子模块的Jar包才能取到配置文件的。

       Jar包本质上是压缩文件,以前也做个在压缩文件中解析配置文件,但感觉不太专业,由于时间赶,不想在网上捞资料,而且靠不靠谱也不一定,于是想到了借鉴Spring中的扫描和解析配置文件的功能代码


       我们经常用如下Spring配置来解析资源文件和扫描class:

       <context:component-scan        base-package="com.manzhizhen.server.service,com.manzhizhen.server.aop" />

       <bean
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:conf/resource1.properties</value>
            </list>
        </property>
    </bean>

        我本地已经有Spring4的源码,于是我直接在源码中搜索base-package关键字,于是定位到ComponentScanBeanDefinitionParser类:

 

Java代码  收藏代码

  1. public class ComponentScanBeanDefinitionParser implements BeanDefinitionParser {  

  2.     private static final String BASE_PACKAGE_ATTRIBUTE = "base-package";  

 然后我搜索哪些类用到了BASE_PACKAGE_ATTRIBUTE,于是找到了ComponentScanBeanDefinitionParser类:

 

 

Java代码  收藏代码

  1. public class ComponentScanBeanDefinitionParser implements BeanDefinitionParser {  

  2.      ... ...  

  3.     @Override  

  4.     public BeanDefinition parse(Element element, ParserContext parserContext) {  

  5.         String[] basePackages = StringUtils.tokenizeToStringArray(element.getAttribute(<strong>BASE_PACKAGE_ATTRIBUTE</strong>),  

  6.                 ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);  

  7.   

  8.         // Actually scan for bean definitions and register them.  

  9.         ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);  

  10.         Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);  

  11.         registerComponents(parserContext.getReaderContext(), beanDefinitions, element);  

  12.   

  13.         return null;  

  14.     }  

 ComponentScanBeanDefinitionParser类的作用就是将解析来的xml元素转换成Bean定义,并将他们注册到上下文中,所以我可以从这里开始追踪Spring是如何根据我们定义的class路径去扫描class文件的。

       其中,element.getAttribute(BASE_PACKAGE_ATTRIBUTE)的值就是我们配置的"com.manzhizhen.server.service,com.manzhizhen.server.aop",而ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS只是在Spring中预定义的配置路径分隔符而已,比如“.;\t\n”,最后经过分隔,得到的String[] basePackages就是com.manzhizhen.server.service和com.manzhizhen.server.aop组成的字符串列表了。

 

        我们发现,代码Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);就已经把我们配置的两个package下的所有class解析出来了,所以我决定看看scanner.doScan(basePackages)里面到底做了什么,于是我们来到了ClassPathBeanDefinitionScanner#doScan

 

Java代码  收藏代码

  1. protected Set<BeanDefinitionHolder> doScan(String... basePackages) {  

  2.     Assert.notEmpty(basePackages, "At least one base package must be specified");  

  3.     Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();  

  4.     for (String basePackage : basePackages) {  

  5.         <strong>Set<BeanDefinition> candidates = findCandidateComponents(basePackage);</strong>  

  6.         for (BeanDefinition candidate : candidates) {  

  7.             ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);  

  8.             candidate.setScope(scopeMetadata.getScopeName());  

  9.             String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);  

  10.             if (candidate instanceof AbstractBeanDefinition) {  

  11.                 postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);  

  12.             }  

  13.             if (candidate instanceof AnnotatedBeanDefinition) {  

  14.                 AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);  

  15.             }  

  16.             if (checkCandidate(beanName, candidate)) {  

  17.                 BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);  

  18.                 definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);  

  19.                 beanDefinitions.add(definitionHolder);  

  20.                 registerBeanDefinition(definitionHolder, this.registry);  

  21.             }  

  22.         }                         

  23.     }  

  24.     return beanDefinitions;  

  25. }  

 由于上面加黑的代码就已经将class扫描出来了,于是去看看findCandidateComponents方法是怎么实现的:

 

Java代码  收藏代码

  1. /** 

  2.  * Scan the class path for candidate components. 

  3.  * @param basePackage the package to check for annotated classes 

  4.  * @return a corresponding Set of autodetected bean definitions 

  5.  */  

  6. public Set<BeanDefinition> findCandidateComponents(String basePackage) {  

  7.     Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>();  

  8.     try {  

  9.         String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +  

  10.                 resolveBasePackage(basePackage) + "/" + this.resourcePattern;  

  11.         Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);  

  12.         boolean traceEnabled = logger.isTraceEnabled();  

  13.         boolean debugEnabled = logger.isDebugEnabled();  

  14.         for (Resource resource : resources) {  

  15.             if (traceEnabled) {  

  16.                 logger.trace("Scanning " + resource);  

  17.             }  

  18.             if (resource.isReadable()) {  

  19.                 try {  

  20.                     MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);  

  21.                     if (isCandidateComponent(metadataReader)) {  

  22.                         ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);  

  23.                         sbd.setResource(resource);  

  24.                         sbd.setSource(resource);  

  25.                         if (isCandidateComponent(sbd)) {  

  26.                             if (debugEnabled) {  

  27.                                 logger.debug("Identified candidate component class: " + resource);  

  28.                             }  

  29.                             candidates.add(sbd);  

  30.                         }  

  31.                         else {  

  32.                             if (debugEnabled) {  

  33.                                 logger.debug("Ignored because not a concrete top-level class: " + resource);  

  34.                             }  

  35.                         }  

  36.                     }  

  37.                     else {  

  38.                         if (traceEnabled) {  

  39.                             logger.trace("Ignored because not matching any filter: " + resource);  

  40.                         }  

  41.                     }  

  42.                 }  

  43.                 catch (Throwable ex) {  

  44.                     throw new BeanDefinitionStoreException(  

  45.                             "Failed to read candidate component class: " + resource, ex);  

  46.                 }  

  47.             }  

  48.             else {  

  49.                 if (traceEnabled) {  

  50.                     logger.trace("Ignored because not readable: " + resource);  

  51.                 }  

  52.             }  

  53.         }  

  54.     }  

  55.     catch (IOException ex) {  

  56.         throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);  

  57.     }  

  58.     return candidates;  

  59. }  

 代码String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                    resolveBasePackage(basePackage) + "/" + this.resourcePattern;将我们的包路径组装成Spring中能识别的格式,如把 “com.manzhizhen.server.service” 变成 "classpath*:com.manzhizhen.server.service/**/*.class",对,就是对前后做了补充,给后面的统一解析操作提供必要的指引。我们发现代码 Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath); 就已经将所有的class扫描出来了,于是我们看看里面做了些什么,于是追踪到了GenericApplicationContext#getResources

Java代码  收藏代码

  1. /** 

  2.  * This implementation delegates to this context's ResourceLoader if it 

  3.  * implements the ResourcePatternResolver interface, falling back to the 

  4.  * default superclass behavior else. 

  5.  * @see #setResourceLoader 

  6.  */  

  7. @Override  

  8. public Resource[] getResources(String locationPattern) throws IOException {  

  9.     if (this.resourceLoader instanceof ResourcePatternResolver) {  

  10.         return ((ResourcePatternResolver) this.resourceLoader).getResources(locationPattern);  

  11.     }  

  12.     return <strong>super.getResources(locationPattern);</strong>  

  13. }  

 加黑部分,发现它是调了父类的方法AbstractApplicationContext#getResources

 

 

Java代码  收藏代码

  1. public Resource[] getResources(String locationPattern) throws IOException {  

  2.     return <strong>this.resourcePatternResolver.getResources(locationPattern);</strong>  

  3. }  

 this.resourcePatternResolver PathMatchingResourcePatternResolver类的对象,我们看看它的getResources 方法:

Java代码  收藏代码

  1. public Resource[] getResources(String locationPattern) throws IOException {  

  2.     Assert.notNull(locationPattern, "Location pattern must not be null");  

  3.     if (<strong>locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)</strong>) {  

  4.         // a class path resource (multiple resources for same name possible)  

  5.         if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {  

  6.             // a class path resource pattern  

  7.             return findPathMatchingResources(locationPattern);  

  8.         }  

  9.         else {  

  10.             // all class path resources with the given name  

  11.             return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));  

  12.         }  

  13.     }  

  14.     else {  

  15.         // Only look for a pattern after a prefix here  

  16.         // (to not get fooled by a pattern symbol in a strange prefix).  

  17.         int prefixEnd = locationPattern.indexOf(":") + 1;  

  18.         if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {  

  19.             // a file pattern  

  20.             return findPathMatchingResources(locationPattern);  

  21.         }  

  22.         else {  

  23.             // a single resource with the given name  

  24.             return new Resource[] {getResourceLoader().getResource(locationPattern)};  

  25.         }  

  26.     }  

  27. }  

 CLASSPATH_ALL_URL_PREFIX 是 PathMatchingResourcePatternResolver 的实现接口ResourcePatternResolver 中定义的常量:

Java代码  收藏代码

  1. /** 

  2.  * Pseudo URL prefix for all matching resources from the class path: "classpath*:" 

  3.  * This differs from ResourceLoader's classpath URL prefix in that it 

  4.  * retrieves all matching resources for a given name (e.g. "/beans.xml"), 

  5.  * for example in the root of all deployed JAR files. 

  6.  * @see org.springframework.core.io.ResourceLoader#CLASSPATH_URL_PREFIX 

  7.  */  

  8. String <strong>CLASSPATH_ALL_URL_PREFIX</strong> = "classpath*:";  

 其值就是前面Spring给包路径加的前缀。

        我们回到 PathMatchingResourcePatternResolver#getResources 的那段代码,继续往下看,getPathMatcher() 返回的是 AntPathMatcher 类的对象,咱们看看它的 isPattern 方法:

Java代码  收藏代码

  1. public boolean isPattern(String path) {  

  2.     return (path.indexOf('*') != -1 || path.indexOf('?') != -1);  

  3. }  

 由于前面Spring对包路径的加工,我们很幸运的就匹配上了,于是我们进入了下面的findPathMatchingResources(locationPattern); 方法,我们看看实现:

Java代码  收藏代码

  1. /** 

  2.  * Find all resources that match the given location pattern via the 

  3.  * Ant-style PathMatcher. Supports resources in jar files and zip files 

  4.  * and in the file system. 

  5.  * @param locationPattern the location pattern to match 

  6.  * @return the result as Resource array 

  7.  * @throws IOException in case of I/O errors 

  8.  * @see #doFindPathMatchingJarResources 

  9.  * @see #doFindPathMatchingFileResources 

  10.  * @see org.springframework.util.PathMatcher 

  11.  */  

  12. protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {  

  13.     String rootDirPath = determineRootDir(locationPattern);  

  14.     String subPattern = locationPattern.substring(rootDirPath.length());  

  15.     Resource[] rootDirResources = getResources(rootDirPath);  

  16.     Set<Resource> result = new LinkedHashSet<Resource>(16);  

  17.     for (Resource rootDirResource : rootDirResources) {  

  18.         rootDirResource = resolveRootDirResource(rootDirResource);  

  19.         if (isJarResource(rootDirResource)) {  

  20.             result.addAll(<strong>doFindPathMatchingJarResources</strong>(rootDirResource, subPattern));  

  21.         }  

  22.         else if (rootDirResource.getURL().getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {  

  23.             result.addAll(VfsResourceMatchingDelegate.findMatchingResources(rootDirResource, subPattern, getPathMatcher()));  

  24.         }  

  25.         else {  

  26.             result.addAll(<strong>doFindPathMatchingFileResources</strong>(rootDirResource, subPattern));  

  27.         }  

  28.     }  

  29.     if (logger.isDebugEnabled()) {  

  30.         logger.debug("Resolved location pattern [" + locationPattern + "] to resources " + result);  

  31.     }  

  32.     return result.toArray(new Resource[result.size()]);  

  33. }  

 第一行 String rootDirPath = determineRootDir(locationPattern);  得到的 rootDirPath 值为“classpath*:com/kuaidadi/liangjian/allconfig/server/service/”, 即资源文件根目录。第二行 String subPattern = locationPattern.substring(rootDirPath.length()); 得到的 subPattern 是 “**/*.class”,即需要扫描的资源文件类型。接下来的 Resource[] rootDirResources = getResources(rootDirPath); 将该资源根路径解析成Spring中的资源对象。 其实 getResources 和 findPathMatchingResources 之间会相互调用。请看上面代码我对两个方法进行了加黑:doFindPathMatchingJarResources 和 doFindPathMatchingFileResources,这两个方法分别完成Jar包和文件系统资源的扫描工作,doFindPathMatchingFileResources方法实现比较简单,文件系统的读取大家都会,咱们看看Spring是如何解析Jar包中的资源的,doFindPathMatchingJarResources 方法源码如下:

Java代码  收藏代码

  1. /** 

  2.  * Find all resources in jar files that match the given location pattern 

  3.  * via the Ant-style PathMatcher. 

  4.  * @param rootDirResource the root directory as Resource 

  5.  * @param subPattern the sub pattern to match (below the root directory) 

  6.  * @return the Set of matching Resource instances 

  7.  * @throws IOException in case of I/O errors 

  8.  * @see java.net.JarURLConnection 

  9.  * @see org.springframework.util.PathMatcher 

  10.  */  

  11. protected Set<Resource> doFindPathMatchingJarResources(Resource rootDirResource, String subPattern)  

  12.         throws IOException {  

  13.   

  14.     URLConnection con = rootDirResource.getURL().openConnection();  

  15.     JarFile jarFile;  

  16.     String jarFileUrl;  

  17.     String rootEntryPath;  

  18.     boolean newJarFile = false;  

  19.   

  20.     if (con instanceof JarURLConnection) {  

  21.         // Should usually be the case for traditional JAR files.  

  22.         JarURLConnection jarCon = (JarURLConnection) con;  

  23.         jarCon.setUseCaches(false);  

  24.         jarFile = jarCon.getJarFile();  

  25.         jarFileUrl = jarCon.getJarFileURL().toExternalForm();  

  26.         JarEntry jarEntry = jarCon.getJarEntry();  

  27.         rootEntryPath = (jarEntry != null ? jarEntry.getName() : "");  

  28.     }  

  29.     else {  

  30.         // No JarURLConnection -> need to resort to URL file parsing.  

  31.         // We'll assume URLs of the format "jar:path!/entry", with the protocol  

  32.         // being arbitrary as long as following the entry format.  

  33.         // We'll also handle paths with and without leading "file:" prefix.  

  34.         String urlFile = rootDirResource.getURL().getFile();  

  35.         int separatorIndex = urlFile.indexOf(ResourceUtils.JAR_URL_SEPARATOR);  

  36.         if (separatorIndex != -1) {  

  37.             jarFileUrl = urlFile.substring(0, separatorIndex);  

  38.             rootEntryPath = urlFile.substring(separatorIndex + ResourceUtils.JAR_URL_SEPARATOR.length());  

  39.             jarFile = getJarFile(jarFileUrl);  

  40.         }  

  41.         else {  

  42.             jarFile = new JarFile(urlFile);  

  43.             jarFileUrl = urlFile;  

  44.             rootEntryPath = "";  

  45.         }  

  46.         newJarFile = true;  

  47.     }  

  48.   

  49.     try {  

  50.         if (logger.isDebugEnabled()) {  

  51.             logger.debug("Looking for matching resources in jar file [" + jarFileUrl + "]");  

  52.         }  

  53.         if (!"".equals(rootEntryPath) && !rootEntryPath.endsWith("/")) {  

  54.             // Root entry path must end with slash to allow for proper matching.  

  55.             // The Sun JRE does not return a slash here, but BEA JRockit does.  

  56.             rootEntryPath = rootEntryPath + "/";  

  57.         }  

  58.         Set<Resource> result = new LinkedHashSet<Resource>(8);  

  59.         for (Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements();) {  

  60.             JarEntry entry = entries.nextElement();  

  61.             String entryPath = entry.getName();  

  62.             if (entryPath.startsWith(rootEntryPath)) {  

  63.                 String relativePath = entryPath.substring(rootEntryPath.length());  

  64.                 if (getPathMatcher().match(subPattern, relativePath)) {  

  65.                     result.add(rootDirResource.createRelative(relativePath));  

  66.                 }  

  67.             }  

  68.         }  

  69.         return result;  

  70.     }  

  71.     finally {  

  72.         // Close jar file, but only if freshly obtained -  

  73.         // not from JarURLConnection, which might cache the file reference.  

  74.         if (newJarFile) {  

  75.             jarFile.close();  

  76.         }  

  77.     }  

  78. }  

 这就拿到了我想要的代码的,我 定义了一个 ResourceTool  类,其中做了简化处理:

Java代码  收藏代码

  1. public class ResourceTool {  

  2.  /** 

  3.   * 获取默认的类加载器 

  4.   *  

  5.   * @return 

  6.   */  

  7.  public static ClassLoader getDefaultClassLoader() {  

  8.      ClassLoader cl = null;  

  9.      try {  

  10.          cl = Thread.currentThread().getContextClassLoader();  

  11.      } catch (Throwable ex) {  

  12.      }  

  13.      if (cl == null) {  

  14.          // No thread context class loader -> use class loader of this class.  

  15.          cl = ClassUtils.class.getClassLoader();  

  16.      }  

  17.   

  18.      return cl;  

  19.  }  

  20.   

  21.  /** 

  22.   * 获取配置文件资源对象 

  23.   *  

  24.   * @param location 

  25.   * @return 

  26.   * @throws IOException 

  27.   */  

  28.  public static List<URL> findAllClassPathResources(String location) throws IOException {  

  29.      String path = location;  

  30.      if (path.startsWith("/")) {  

  31.          path = path.substring(1);  

  32.      }  

  33.   

  34.      Enumeration<URL> resourceUrls = getDefaultClassLoader().getResources(location);  

  35.      List<URL> result = Lists.newArrayList();  

  36.      while (resourceUrls.hasMoreElements()) {  

  37.   

  38.          result.add(resourceUrls.nextElement());  

  39.      }  

  40.   

  41.      return result;  

  42.  }  

  43.   

  44.  /** 

  45.   * 获取指定路径下的指定文件列表 

  46.   *  

  47.   * @param rootFile           文件路径 

  48.   * @param extensionName 文件扩展名 

  49.   * @return 

  50.   */  

  51.  public static List<File> getFiles(File rootFile, String extensionName) {  

  52.      List<File> fileList = Lists.newArrayList();  

  53.   

  54.      String tail = null;  

  55.      if (extensionName == null) {  

  56.          tail = "";  

  57.      } else {  

  58.          tail = "." + extensionName;  

  59.      }  

  60.   

  61.      if (rootFile == null) {  

  62.          return fileList;  

  63.   

  64.      } else if (rootFile.isFile() && rootFile.getName().endsWith(tail)) {  

  65.          fileList.add(rootFile);  

  66.          return fileList;  

  67.   

  68.      } else if (rootFile.isDirectory()) {  

  69.          File[] files = rootFile.listFiles();  

  70.          for (File file : files) {  

  71.              if (file.isFile() && file.getName().endsWith(tail)) {  

  72.                  fileList.add(file);  

  73.   

  74.              } else if (file.isDirectory()) {  

  75.                  fileList.addAll(getFiles(file, extensionName));  

  76.              }  

  77.          }  

  78.      }  

  79.   

  80.      return fileList;  

  81.  }  

  82.   

  83.  public static List<URL> <strong>getJarUrl</strong>(URL rootUrl, String extensionName) throws IOException {  

  84.      List<URL> result = Lists.newArrayList();  

  85.   

  86.      if (rootUrl == null || !"jar".equals(rootUrl.getProtocol())) {  

  87.          return result;  

  88.      }  

  89.   

  90.      if (StringUtils.isNotBlank(extensionName)) {  

  91.          extensionName = "." + extensionName;  

  92.      }  

  93.   

  94.      if (extensionName == null) {  

  95.          extensionName = "";  

  96.      }  

  97.   

  98.      URLConnection con = rootUrl.openConnection();  

  99.   

  100.      JarURLConnection jarCon = (JarURLConnection) con;  

  101.      jarCon.setUseCaches(false);  

  102.      JarFile jarFile = jarCon.getJarFile();  

  103.      JarEntry jarEntry = jarCon.getJarEntry();  

  104.      String rootEntryPath = (jarEntry != null ? jarEntry.getName() : "");  

  105.   

  106.      if (!"".equals(rootEntryPath) && !rootEntryPath.endsWith("/")) {  

  107.          rootEntryPath = rootEntryPath + "/";  

  108.      }  

  109.   

  110.      for (Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements();) {  

  111.          JarEntry entry = entries.nextElement();  

  112.          String entryPath = entry.getName();  

  113.   

  114.          if (entryPath.startsWith(rootEntryPath)) {  

  115.              String relativePath = entryPath.substring(rootEntryPath.length());  

  116.              if (relativePath.endsWith(".service")) {  

  117.                  result.add(createRelative(rootUrl, relativePath));  

  118.   

  119.              }  

  120.          }  

  121.      }  

  122.   

  123.      return result;  

  124.   

  125.  }  

  126.   

  127.  private static URL createRelative(URL url, String relativePath) throws MalformedURLException {  

  128.      if (relativePath.startsWith("/")) {  

  129.          relativePath = relativePath.substring(1);  

  130.      }  

  131.   

  132.      return new URL(url, relativePath);  

  133.  }  

 使用举例:

Java代码  收藏代码

  1.    /** 

  2.     * 将配置内容转换成内置对象 

  3.     *  

  4.     * @return 

  5.     */  

  6.    private Map<String, ServiceSetting> getServiceSettingList(String path) {  

  7.        Map<String, ServiceSetting> map = Maps.newHashMap();  

  8.   

  9.        try {  

  10.            List<URL> urlList = ResourceTool.findAllClassPathResources(path);  

  11.            for (URL url : urlList) {  

  12.                String protocol = url.getProtocol();  

  13.                // org.springframework.util.ResourceUtils  

  14.                if (ResourceUtils.URL_PROTOCOL_JAR.equals(protocol)) {  

  15.                    // 资源文件扩展名为"service"  

  16.                    List<URL> result = ResourceTool.getJarUrl(url, "service");  

  17.                    for (URL jarUrl : result) {  

  18.                        URLConnection connection = jarUrl.openConnection();  

  19.                        try {  

  20.                            /** 

  21.                             * 得到InputStream,即可解析配置文件 

  22.                             */  

  23.                            ServiceSetting serviceSetting = reloadServiceSetting(connection.getInputStream());  

  24.   

  25.                            /** 

  26.                             * 检查服务配置正确性 

  27.                             */  

  28.                            boolean check = checkServiceSetting(serviceSetting);  

  29.   

  30.                            if (check) {  

  31.                                map.put(serviceSetting.getName(), serviceSetting);  

  32.   

  33.                                logger.info("成功加载文件:" + jarUrl.getFile() + ", serviceSetting:"  

  34.                                            + JsonUtil.toJson(serviceSetting));  

  35.   

  36.                            }  

  37.   

  38.                        } catch (Exception e) {  

  39.                           // TODO:  

  40.   

  41.                        }  

  42.   

  43.                    }  

  44.   

  45.                } else if (ResourceUtils.URL_PROTOCOL_FILE.endsWith(protocol)) {  

  46.                    // <a class="header">org</a>.<a class="header">springframework</a>.<a class="header">util</a>.StringUtils  

  47.                    File file = new File(  

  48.                        new URI(StringUtils.replace(url.toString(), " ""%20")).getSchemeSpecificPart());  

  49.  ////  资源文件扩展名为"service"                     

  50. List<File> fileList = ResourceTool.getFiles(file, "service");  

  51.   

  52.                    for (File serviceFile : fileList) {  

  53.                        ServiceSetting serviceSetting = reloadServiceSetting(new FileInputStream(serviceFile));  

  54.   

  55.                        /** 

  56.                         * 检查服务配置正确性 

  57.                         */  

  58.                        boolean check = checkServiceSetting(serviceSetting);  

  59.   

  60.                        if (check) {  

  61.                            map.put(serviceSetting.getName(), serviceSetting);  

  62.   

  63.                            logger.info("成功加载文件:" + serviceFile.getPath() + ", serviceSetting:"  

  64.                                        + JsonUtil.toJson(serviceSetting));  

  65.   

  66.                        }  

  67.                    }  

  68.   

  69.                }  

  70.            }  

  71.            return map;  

  72.        } catch (Exception e) {  

  73.           // TODO:  

  74.        }  

  75.    }  

 

是不是相当简单?


你可能感兴趣的:(spring)