/** 解析<code>TypeFilter</code>s。 */ private void parseTypeFilters( Element element, ClassLoader classLoader, List<TypeFilter> includes, List<TypeFilter> excludes) { ElementSelector includeSelector = and(sameNs(element), name("include-filter")); ElementSelector excludeSelector = and(sameNs(element), name("exclude-filter")); for (Element subElement : subElements(element)) { if (includeSelector.accept(subElement)) { TypeFilter filter = createTypeFilter(subElement, classLoader); if (filter != null) { includes.add(filter); } } else if (excludeSelector.accept(subElement)) { TypeFilter filter = createTypeFilter(subElement, classLoader); if (filter != null) { excludes.add(filter); } } } }
@Override protected void doParse( Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { Map<String, ParsingModuleInfo> classes = parseSpecificBeans( element, parserContext, builder.getRawBeanDefinition(), and(beansNs(), name("bean"))); ElementSelector searchPackages = and(sameNs(element), name("search-packages")); ElementSelector searchClasses = and(sameNs(element), name("search-classes")); ModuleDefinitionScanner scanner = getScanner(parserContext); for (Element subElement : subElements(element)) { Pattern classNamePattern = null; String typeName = null; String moduleName = null; String classResourceName = null; if (searchPackages.accept(subElement)) { String packageName = assertNotNull( normalizeClassName(subElement.getAttribute("packages")), "no package name provided for search-packages"); classNamePattern = compileClassName(packageName, MATCH_PREFIX); typeName = assertNotNull(trimToNull(subElement.getAttribute("type")), "no type name provided"); classResourceName = classNameToPathName(packageName) + "/**/*.class"; log.trace("Searching in packages: {}, moduleType={}", packageName, typeName); } else if (searchClasses.accept(subElement)) { String className = assertNotNull( normalizeClassName(subElement.getAttribute("classes")), "no class name provided for search-classes"); classNamePattern = compileClassName(className, MATCH_PREFIX); typeName = assertNotNull(trimToNull(subElement.getAttribute("type")), "no type name provided"); moduleName = assertNotNull(trimToNull(subElement.getAttribute("name")), "no module name provided"); classResourceName = classNameToPathName(className); if (classResourceName.endsWith("**")) { classResourceName += "/*.class"; } else { classResourceName += ".class"; } log.trace( "Searching for classes: {}, moduleType={}, moduleName={}", new Object[] {className, typeName, moduleName}); } boolean includeAbstractClasses = "true".equalsIgnoreCase(trimToNull(subElement.getAttribute("includeAbstractClasses"))); if (classResourceName != null) { // 处理所有的include/exclude filters ClassLoader classLoader = scanner.getResourceLoader().getClassLoader(); List<TypeFilter> includes = createLinkedList(); List<TypeFilter> excludes = createLinkedList(); parseTypeFilters(subElement, classLoader, includes, excludes); ModuleTypeFilter filter = new ModuleTypeFilter(classes, classNamePattern, typeName, moduleName, includes); // 事实上,只有一个顶级的include filter,其它的include filter被这一个moduleTypeFilter所调用。 scanner.addIncludeFilter(filter); // Exclude filter比较简单,直接加到scanner中即可。 for (TypeFilter exclude : excludes) { scanner.addExcludeFilter(exclude); } scanner.setBeanNameGenerator(filter); scanner.setResourcePattern(classResourceName.replace('?', '*')); scanner.setIncludeAbstractClasses(includeAbstractClasses); scanner.setBeanDefinitionDefaults(getBeanDefinitionDefaults(subElement, parserContext)); int found = scanner.scan(""); log.debug("Found {} module classes with pattern: {}", found, classResourceName); } } postProcessItems(element, parserContext, builder, classes, "search-packages or search-classes"); }
@Override protected void doParse( Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { Map<String, ParsingModuleInfo> scripts = parseSpecificBeans(element, parserContext, builder.getRawBeanDefinition(), ns(LANG_URI)); ElementSelector searchFolders = and(sameNs(element), name("search-folders")); ElementSelector searchFiles = and(sameNs(element), name("search-files")); for (Element subElement : subElements(element)) { String prefix = null; String typeName = null; String moduleName = null; Pattern scriptNamePattern = null; String scriptResourceName = null; String language = null; if (searchFolders.accept(subElement)) { String folderName = assertNotNull( normalizePathName(subElement.getAttribute("folders")), "no folder name provided for search-folders"); // 取prefix prefix = getPrefix(folderName); if (prefix != null) { folderName = folderName.substring(prefix.length() + 1); } // folderName不以/开始 if (folderName.startsWith("/")) { folderName = folderName.substring(1); } scriptNamePattern = compilePathName(folderName); typeName = assertNotNull(trimToNull(subElement.getAttribute("type")), "no type name provided"); language = trimToNull(subElement.getAttribute("language")); scriptResourceName = folderName + "/**/*.*"; log.trace( "Searching in folders: {}, moduleType={}, language={}", new Object[] {folderName, typeName, language == null ? "auto" : language}); } else if (searchFiles.accept(subElement)) { String fileName = assertNotNull( normalizePathName(subElement.getAttribute("files")), "no script file name provided for search-files"); // fileName不以/结尾 assertTrue(!fileName.endsWith("/"), "invalid script file name: %s", fileName); // 取prefix prefix = getPrefix(fileName); if (prefix != null) { fileName = fileName.substring(prefix.length() + 1); } // fileName不以/开始 if (fileName.startsWith("/")) { fileName = fileName.substring(1); } scriptNamePattern = compilePathName(fileName); typeName = assertNotNull(trimToNull(subElement.getAttribute("type")), "no type name provided"); moduleName = assertNotNull(trimToNull(subElement.getAttribute("name")), "no module name provided"); language = trimToNull(subElement.getAttribute("language")); scriptResourceName = fileName; log.trace( "Searching for script files: {}, moduleType={}, moduleName={}, language={}", new Object[] {fileName, typeName, moduleName, language == null ? "auto" : language}); } if (scriptResourceName != null) { scriptResourceName = prefix == null ? scriptResourceName : prefix + ":" + scriptResourceName; // 扫描scripts ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver( parserContext.getReaderContext().getResourceLoader()); int found = 0; try { Resource[] resources = resolver.getResources(scriptResourceName.replace('?', '*')); BeanDefinitionDefaults defaults = getBeanDefinitionDefaults(subElement, parserContext); ParsingModuleMatcher matcher = new ParsingModuleMatcher(scripts, scriptNamePattern, typeName, moduleName) { @Override protected String getName(String name, String itemName) { String ext = getExt(itemName); if (ext != null && name.endsWith("." + ext)) { return name.substring(0, name.length() - ext.length() - 1); } return name; } }; for (Resource resource : resources) { if (resource.isReadable()) { URI uri = resource.getURI(); if (uri == null) { continue; } String resourceName = uri.normalize().toString(); if (matcher.doMatch(resourceName)) { BeanDefinition scriptBean = createScriptBean(subElement, parserContext, resourceName, language, defaults); String beanName = matcher.generateBeanName(resourceName, parserContext.getRegistry()); parserContext.getRegistry().registerBeanDefinition(beanName, scriptBean); found++; } } } } catch (IOException e) { parserContext .getReaderContext() .error("Failed to scan resources: " + scriptResourceName, subElement, e); return; } log.debug("Found {} module scripts with pattern: {}", found, scriptResourceName); } } postProcessItems(element, parserContext, builder, scripts, "search-folders or search-files"); }