
Spring源码解析-自定义标签解析和SPI机制-3
1. 涉及SPI机制地方
自定义标签:例如:context aop 等等都是自定义标签,需要利用SPI机制 默认标签中的自定义元素加载也涉及到SPI机制2. SPI机制:
SPI就是一个服务的扩展机制,可以把接口的实现类配置到META-INF元数据区,框架启动时加载到缓存,最初的版本是jdk中实现的,后来在spring、springboot、dubbo中都有相应的使用。
3. JDK的SPI机制:
META-INF下创建services目录,然后以接口全限定名为文件名,将实现类的全限定名放进去,这样运行程序时,会加载实现类的名称进jvm,调用的时候会调用newInstance()方法实例化对象。
示例:
创建一个IAnimal接口:package com.hello.spi; public interface IAnimal { void sing(); }
创建两个实现类:
package com.hello.spi; public class Cat implements IAnimal { @Override public void sing() { System.out.println("cat sing......"); } }
package com.hello.spi; public class Dog implements IAnimal { @Override public void sing() { System.out.println("dog sing......"); } }
//全路径需和类路径保持一致 resource\META-INF.services\com.hello.spi.IAnimal //此路径文件下有 com.hello.spi.Cat com.hello.spi.Dog
测试代码:
public class TestSPI { public static void main(String[] args) { ServiceLoader<IAnimal> animals = ServiceLoader.load(IAnimal.class); for (Iterator<IAnimal> iter = animals.iterator();iter.hasNext();) { IAnimal animal = iter.next(); animal.sing(); } } }
5. spring的spi机制:
获取spring中所有jar包里面的"META-INF/spring.handlers"文件,并且建立映射关系 spring的类DefaultNamespaceHandlerResolver这个类,会懒加载spring.handler文件内配置的实现类进内存 读取META-INF/spring.handlers目录下的实现类进jvm 然后缓存到handlerMappings,等待后面使用 这个是 spring-context工程下spring.handlers文件内容: key为命名空间url、value为类的全限定名,加载完成后会缓存到handlerMappings中//此方法上一篇中有提到 private Map<String, Object> getHandlerMappings() { Map<String, Object> handlerMappings = this.handlerMappings; if (handlerMappings == null) { synchronized (this) { handlerMappings = this.handlerMappings; if (handlerMappings == null) { if (logger.isTraceEnabled()) { logger.trace("Loading NamespaceHandler mappings from [" + this.handlerMappingsLocation + "]"); } try { //加载"META-INF/spring.handlers"文件过程 Properties mappings = PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader); if (logger.isTraceEnabled()) { logger.trace("Loaded NamespaceHandler mappings: " + mappings); } //所有"META-INF/spring.handlers"文件里面的内容建立映射关系 handlerMappings = new ConcurrentHashMap<>(mappings.size()); CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings); this.handlerMappings = handlerMappings; } catch (IOException ex) { throw new IllegalStateException( "Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex); } } } } return handlerMappings; }
6. 自定义标签的解析
6.1 解析自定义元素
public BeanDefinition parseCustomElement(Element ele) { return parseCustomElement(ele, null); } public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) { // 解析到自定义元素的命名空间,例如:context元素命名空间 http://www.springframework.org/schema/context String namespaceUri = getNamespaceURI(ele); if (namespaceUri == null) { return null; } // 根据url找命名空间handler NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler == null) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); return null; } return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); }
6.2 寻找命名空间对象(此方法上一章有用到)
public NamespaceHandler resolve(String namespaceUri) { //获取spring中所有jar包里面的 "META-INF/spring.handlers"文件,并且建立映射关系 Map<String, Object> handlerMappings = getHandlerMappings(); //根据namespaceUri:http://www.springframework.org/schema/p,获取到这个命名空间的处理类 // 根据url找到对应的全限定类名 Object handlerOrClassName = handlerMappings.get(namespaceUri); if (handlerOrClassName == null) { return null; } //如果时对象直接返回,说明不是第一次使用 else if (handlerOrClassName instanceof NamespaceHandler) { return (NamespaceHandler) handlerOrClassName; } // 首次调用,会走下述逻辑 // 1.根据类名加载此类,创建class对象 // 2.根据class反射创建对象 // 3.初始化init // 4.放入缓存 // 5.返回这个对象 else { String className = (String) handlerOrClassName; try { //反射出来类 Class<?> handlerClass = ClassUtils.forName(className, this.classLoader); if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) { throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri + "] does not implement the [" + NamespaceHandler.class.getName() + "] interface"); } //实例化 NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass); //调用处理类的init方法,在init方法中完成标签元素解析类的注册***重要 namespaceHandler.init(); handlerMappings.put(namespaceUri, namespaceHandler); return namespaceHandler; } // catch略...... } }
6.3 初始化,把属性和解析器缓存映射,主要的处理缓存逻辑都在父类NamespaceHandlerSupport中, 这样初始化之后,这个NamespaceHandler就包含了众多解析器。
public class ContextNamespaceHandler extends NamespaceHandlerSupport { @Override public void init() { registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser()); registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser()); registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser()); registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser()); registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser()); registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser()); registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser()); } } //NamespaceHandlerSupport类中 protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) { this.parsers.put(elementName, parser); }
6.4 跳回到6.1拿到NamespaceHandler,开始解析
public BeanDefinition parse(Element element, ParserContext parserContext) { BeanDefinitionParser parser = findParserForElement(element, parserContext); return (parser != null ? parser.parse(element, parserContext) : null); } private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) { String localName = parserContext.getDelegate().getLocalName(element); //从缓存中拿到component-scan的解析器 BeanDefinitionParser parser = this.parsers.get(localName); if (parser == null) { parserContext.getReaderContext().fatal( "Cannot locate BeanDefinitionParser for element [" + localName + "]", element); } return parser; }
6.5 拿到解析器,跳转至ComponentScanBeanDefinitionParser,开始解析
public BeanDefinition parse(Element element, ParserContext parserContext) { String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE); basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage); String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); // Actually scan for bean definitions and register them. ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages); registerComponents(parserContext.getReaderContext(), beanDefinitions, element); return null; }
6.6 创建一个扫描器
protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) { //使用默认过滤器 boolean useDefaultFilters = true; if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) { useDefaultFilters = Boolean.valueOf(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)); } // Delegate bean definition registration to scanner class. //创建扫描器 ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters); scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults()); scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns()); if (element.hasAttribute(RESOURCE_PATTERN_ATTRIBUTE)) { scanner.setResourcePattern(element.getAttribute(RESOURCE_PATTERN_ATTRIBUTE)); } try { parseBeanNameGenerator(element, scanner); } catch (Exception ex) { parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause()); } try { parseScope(element, scanner); } catch (Exception ex) { parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause()); } parseTypeFilters(element, scanner, parserContext); return scanner; }
protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) { return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters, readerContext.getEnvironment(), readerContext.getResourceLoader()); } public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment, @Nullable ResourceLoader resourceLoader) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); this.registry = registry; if (useDefaultFilters) { //使用默认过滤器,注册默认过滤器 registerDefaultFilters(); } setEnvironment(environment); setResourceLoader(resourceLoader); }
6.7 注册过滤器,支持注解扫描
protected void registerDefaultFilters() { this.includeFilters.add(new AnnotationTypeFilter(Component.class)); ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader(); try { this.includeFilters.add(new AnnotationTypeFilter( ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false)); logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning"); } catch (ClassNotFoundException ex) { // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip. } try { this.includeFilters.add(new AnnotationTypeFilter( ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false)); logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning"); } catch (ClassNotFoundException ex) { // JSR-330 API not available - simply skip. } }
6.8 跳回到6.5,创建扫描器完成后,就可以扫描basePackages包了
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages); protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>(); for (String basePackage : basePackages) { // 寻找符合条件的类,有Component注解的 Set<BeanDefinition> candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) { ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); if (candidate instanceof AbstractBeanDefinition) { postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } if (checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); //把BeanDefinition注册到spring的缓存中 registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; }
6.9 寻找符合条件的类
public Set<BeanDefinition> findCandidateComponents(String basePackage) { if (this.componentsIndex != null && indexSupportsIncludeFilters()) { return addCandidateComponentsFromIndex(this.componentsIndex, basePackage); } else { //看此方法 return scanCandidateComponents(basePackage); } } private Set<BeanDefinition> scanCandidateComponents(String basePackage) { Set<BeanDefinition> candidates = new LinkedHashSet<>(); try { String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern; //这里递归寻找文件*****重要 Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); for (Resource resource : resources) { if (traceEnabled) { logger.trace("Scanning " + resource); } if (resource.isReadable()) { try { //拿到扫描路径下的资源,然后获取元数据信息,根据元素据信息判断是否满足条件 MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); if (isCandidateComponent(metadataReader)) { ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); sbd.setResource(resource); sbd.setSource(resource); if (isCandidateComponent(sbd)) { if (debugEnabled) { logger.debug("Identified candidate component class: " + resource); } candidates.add(sbd); } else { if (debugEnabled) { logger.debug("Ignored because not a concrete top-level class: " + resource); } } } else { if (traceEnabled) { logger.trace("Ignored because not matching any filter: " + resource); } } } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to read candidate component class: " + resource, ex); } } else { if (traceEnabled) { logger.trace("Ignored because not readable: " + resource); } } } } catch (IOException ex) { throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); } return candidates; }
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException { //排除掉的组件 for (TypeFilter tf : this.excludeFilters) { if (tf.match(metadataReader, getMetadataReaderFactory())) { return false; } } //包含的组件 for (TypeFilter tf : this.includeFilters) { if (tf.match(metadataReader, getMetadataReaderFactory())) { return isConditionMatch(metadataReader); } } return false; }
6.10 跳回6.7查看注册器过滤器类型AnnotationTypeFilter,其父类AbstractTypeHierarchyTraversingFilter
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { // This method optimizes avoiding unnecessary creation of ClassReaders // as well as visiting over those readers. if (matchSelf(metadataReader)) { return true; } ClassMetadata metadata = metadataReader.getClassMetadata(); if (matchClassName(metadata.getClassName())) { return true; } if (this.considerInherited) { String superClassName = metadata.getSuperClassName(); if (superClassName != null) { // Optimization to avoid creating ClassReader for super class. Boolean superClassMatch = matchSuperClass(superClassName); if (superClassMatch != null) { if (superClassMatch.booleanValue()) { return true; } } else { // Need to read super class to determine a match... try { if (match(metadata.getSuperClassName(), metadataReaderFactory)) { return true; } } catch (IOException ex) { logger.debug("Could not read super class [" + metadata.getSuperClassName() + "] of type-filtered class [" + metadata.getClassName() + "]"); } } } } if (this.considerInterfaces) { for (String ifc : metadata.getInterfaceNames()) { // Optimization to avoid creating ClassReader for super class Boolean interfaceMatch = matchInterface(ifc); if (interfaceMatch != null) { if (interfaceMatch.booleanValue()) { return true; } } else { // Need to read interface to determine a match... try { if (match(ifc, metadataReaderFactory)) { return true; } } catch (IOException ex) { logger.debug("Could not read interface [" + ifc + "] for type-filtered class [" + metadata.getClassName() + "]"); } } } } return false; }
6.11 跳转回子类进行判断
protected boolean matchSelf(MetadataReader metadataReader) { AnnotationMetadata metadata = metadataReader.getAnnotationMetadata(); return metadata.hasAnnotation(this.annotationType.getName()) || (this.considerMetaAnnotations && metadata.hasMetaAnnotation(this.annotationType.getName())); }
6.12 跳转回6.9,如果发现这个类上面有Component注解信息,那么就符合条件。对于符合条件的,就会创建一个beanDefinition对象,然后将元数据信息封装进去,并放入容器中,最后返回
6.13 跳回6.8,拿到candidates后,就会遍历处理,返回beanDefinition集合,结合6.5,然后将beanDefinition集合注册到spring容器中,这样这个context的自定义标签解析完毕。
<!--配置扫描路径样例--> <context:component-scan base-package="com.hello" />
总结
上面是以context:component-scan这个自定义标签为例,分析了解析的流程,大概流程如下: 获取元素命名空间url ,nameSpaceUrl 根据namespaceUrl找到nameSpaceHandler,这个使用到了spi懒加载机制(初次获取会反射创建handler对象,然后缓存) 创建handler后,会init初始化,初始化的过程中会缓存各种解析器 根据元素的localname,查询到解析器,然后调用解析器的parse方法开始解析 无论是默认标签还是自定义标签,它们最终都是生成beanDefinition对象,然后注册到beanDefinitionMaps中缓存。进击的萝卜头
实践是检验真理的唯一标准!
0 条评论
进击的萝卜头
实践是检验真理的唯一标准!
宣传栏
目录
1. 涉及SPI机制地方
自定义标签:例如:context aop 等等都是自定义标签,需要利用SPI机制 默认标签中的自定义元素加载也涉及到SPI机制2. SPI机制:
SPI就是一个服务的扩展机制,可以把接口的实现类配置到META-INF元数据区,框架启动时加载到缓存,最初的版本是jdk中实现的,后来在spring、springboot、dubbo中都有相应的使用。
3. JDK的SPI机制:
META-INF下创建services目录,然后以接口全限定名为文件名,将实现类的全限定名放进去,这样运行程序时,会加载实现类的名称进jvm,调用的时候会调用newInstance()方法实例化对象。
示例:
创建一个IAnimal接口:package com.hello.spi; public interface IAnimal { void sing(); }
创建两个实现类:
package com.hello.spi; public class Cat implements IAnimal { @Override public void sing() { System.out.println("cat sing......"); } }
package com.hello.spi; public class Dog implements IAnimal { @Override public void sing() { System.out.println("dog sing......"); } }
//全路径需和类路径保持一致 resource\META-INF.services\com.hello.spi.IAnimal //此路径文件下有 com.hello.spi.Cat com.hello.spi.Dog
测试代码:
public class TestSPI { public static void main(String[] args) { ServiceLoader<IAnimal> animals = ServiceLoader.load(IAnimal.class); for (Iterator<IAnimal> iter = animals.iterator();iter.hasNext();) { IAnimal animal = iter.next(); animal.sing(); } } }
5. spring的spi机制:
获取spring中所有jar包里面的"META-INF/spring.handlers"文件,并且建立映射关系 spring的类DefaultNamespaceHandlerResolver这个类,会懒加载spring.handler文件内配置的实现类进内存 读取META-INF/spring.handlers目录下的实现类进jvm 然后缓存到handlerMappings,等待后面使用 这个是 spring-context工程下spring.handlers文件内容: key为命名空间url、value为类的全限定名,加载完成后会缓存到handlerMappings中//此方法上一篇中有提到 private Map<String, Object> getHandlerMappings() { Map<String, Object> handlerMappings = this.handlerMappings; if (handlerMappings == null) { synchronized (this) { handlerMappings = this.handlerMappings; if (handlerMappings == null) { if (logger.isTraceEnabled()) { logger.trace("Loading NamespaceHandler mappings from [" + this.handlerMappingsLocation + "]"); } try { //加载"META-INF/spring.handlers"文件过程 Properties mappings = PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader); if (logger.isTraceEnabled()) { logger.trace("Loaded NamespaceHandler mappings: " + mappings); } //所有"META-INF/spring.handlers"文件里面的内容建立映射关系 handlerMappings = new ConcurrentHashMap<>(mappings.size()); CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings); this.handlerMappings = handlerMappings; } catch (IOException ex) { throw new IllegalStateException( "Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex); } } } } return handlerMappings; }
6. 自定义标签的解析
6.1 解析自定义元素
public BeanDefinition parseCustomElement(Element ele) { return parseCustomElement(ele, null); } public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) { // 解析到自定义元素的命名空间,例如:context元素命名空间 http://www.springframework.org/schema/context String namespaceUri = getNamespaceURI(ele); if (namespaceUri == null) { return null; } // 根据url找命名空间handler NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler == null) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); return null; } return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); }
6.2 寻找命名空间对象(此方法上一章有用到)
public NamespaceHandler resolve(String namespaceUri) { //获取spring中所有jar包里面的 "META-INF/spring.handlers"文件,并且建立映射关系 Map<String, Object> handlerMappings = getHandlerMappings(); //根据namespaceUri:http://www.springframework.org/schema/p,获取到这个命名空间的处理类 // 根据url找到对应的全限定类名 Object handlerOrClassName = handlerMappings.get(namespaceUri); if (handlerOrClassName == null) { return null; } //如果时对象直接返回,说明不是第一次使用 else if (handlerOrClassName instanceof NamespaceHandler) { return (NamespaceHandler) handlerOrClassName; } // 首次调用,会走下述逻辑 // 1.根据类名加载此类,创建class对象 // 2.根据class反射创建对象 // 3.初始化init // 4.放入缓存 // 5.返回这个对象 else { String className = (String) handlerOrClassName; try { //反射出来类 Class<?> handlerClass = ClassUtils.forName(className, this.classLoader); if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) { throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri + "] does not implement the [" + NamespaceHandler.class.getName() + "] interface"); } //实例化 NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass); //调用处理类的init方法,在init方法中完成标签元素解析类的注册***重要 namespaceHandler.init(); handlerMappings.put(namespaceUri, namespaceHandler); return namespaceHandler; } // catch略...... } }
6.3 初始化,把属性和解析器缓存映射,主要的处理缓存逻辑都在父类NamespaceHandlerSupport中, 这样初始化之后,这个NamespaceHandler就包含了众多解析器。
public class ContextNamespaceHandler extends NamespaceHandlerSupport { @Override public void init() { registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser()); registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser()); registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser()); registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser()); registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser()); registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser()); registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser()); } } //NamespaceHandlerSupport类中 protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) { this.parsers.put(elementName, parser); }
6.4 跳回到6.1拿到NamespaceHandler,开始解析
public BeanDefinition parse(Element element, ParserContext parserContext) { BeanDefinitionParser parser = findParserForElement(element, parserContext); return (parser != null ? parser.parse(element, parserContext) : null); } private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) { String localName = parserContext.getDelegate().getLocalName(element); //从缓存中拿到component-scan的解析器 BeanDefinitionParser parser = this.parsers.get(localName); if (parser == null) { parserContext.getReaderContext().fatal( "Cannot locate BeanDefinitionParser for element [" + localName + "]", element); } return parser; }
6.5 拿到解析器,跳转至ComponentScanBeanDefinitionParser,开始解析
public BeanDefinition parse(Element element, ParserContext parserContext) { String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE); basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage); String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); // Actually scan for bean definitions and register them. ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages); registerComponents(parserContext.getReaderContext(), beanDefinitions, element); return null; }
6.6 创建一个扫描器
protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) { //使用默认过滤器 boolean useDefaultFilters = true; if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) { useDefaultFilters = Boolean.valueOf(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)); } // Delegate bean definition registration to scanner class. //创建扫描器 ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters); scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults()); scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns()); if (element.hasAttribute(RESOURCE_PATTERN_ATTRIBUTE)) { scanner.setResourcePattern(element.getAttribute(RESOURCE_PATTERN_ATTRIBUTE)); } try { parseBeanNameGenerator(element, scanner); } catch (Exception ex) { parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause()); } try { parseScope(element, scanner); } catch (Exception ex) { parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause()); } parseTypeFilters(element, scanner, parserContext); return scanner; }
protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) { return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters, readerContext.getEnvironment(), readerContext.getResourceLoader()); } public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment, @Nullable ResourceLoader resourceLoader) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); this.registry = registry; if (useDefaultFilters) { //使用默认过滤器,注册默认过滤器 registerDefaultFilters(); } setEnvironment(environment); setResourceLoader(resourceLoader); }
6.7 注册过滤器,支持注解扫描
protected void registerDefaultFilters() { this.includeFilters.add(new AnnotationTypeFilter(Component.class)); ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader(); try { this.includeFilters.add(new AnnotationTypeFilter( ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false)); logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning"); } catch (ClassNotFoundException ex) { // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip. } try { this.includeFilters.add(new AnnotationTypeFilter( ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false)); logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning"); } catch (ClassNotFoundException ex) { // JSR-330 API not available - simply skip. } }
6.8 跳回到6.5,创建扫描器完成后,就可以扫描basePackages包了
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages); protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>(); for (String basePackage : basePackages) { // 寻找符合条件的类,有Component注解的 Set<BeanDefinition> candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) { ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); if (candidate instanceof AbstractBeanDefinition) { postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } if (checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); //把BeanDefinition注册到spring的缓存中 registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; }
6.9 寻找符合条件的类
public Set<BeanDefinition> findCandidateComponents(String basePackage) { if (this.componentsIndex != null && indexSupportsIncludeFilters()) { return addCandidateComponentsFromIndex(this.componentsIndex, basePackage); } else { //看此方法 return scanCandidateComponents(basePackage); } } private Set<BeanDefinition> scanCandidateComponents(String basePackage) { Set<BeanDefinition> candidates = new LinkedHashSet<>(); try { String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern; //这里递归寻找文件*****重要 Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); for (Resource resource : resources) { if (traceEnabled) { logger.trace("Scanning " + resource); } if (resource.isReadable()) { try { //拿到扫描路径下的资源,然后获取元数据信息,根据元素据信息判断是否满足条件 MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); if (isCandidateComponent(metadataReader)) { ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); sbd.setResource(resource); sbd.setSource(resource); if (isCandidateComponent(sbd)) { if (debugEnabled) { logger.debug("Identified candidate component class: " + resource); } candidates.add(sbd); } else { if (debugEnabled) { logger.debug("Ignored because not a concrete top-level class: " + resource); } } } else { if (traceEnabled) { logger.trace("Ignored because not matching any filter: " + resource); } } } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to read candidate component class: " + resource, ex); } } else { if (traceEnabled) { logger.trace("Ignored because not readable: " + resource); } } } } catch (IOException ex) { throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); } return candidates; }
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException { //排除掉的组件 for (TypeFilter tf : this.excludeFilters) { if (tf.match(metadataReader, getMetadataReaderFactory())) { return false; } } //包含的组件 for (TypeFilter tf : this.includeFilters) { if (tf.match(metadataReader, getMetadataReaderFactory())) { return isConditionMatch(metadataReader); } } return false; }
6.10 跳回6.7查看注册器过滤器类型AnnotationTypeFilter,其父类AbstractTypeHierarchyTraversingFilter
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { // This method optimizes avoiding unnecessary creation of ClassReaders // as well as visiting over those readers. if (matchSelf(metadataReader)) { return true; } ClassMetadata metadata = metadataReader.getClassMetadata(); if (matchClassName(metadata.getClassName())) { return true; } if (this.considerInherited) { String superClassName = metadata.getSuperClassName(); if (superClassName != null) { // Optimization to avoid creating ClassReader for super class. Boolean superClassMatch = matchSuperClass(superClassName); if (superClassMatch != null) { if (superClassMatch.booleanValue()) { return true; } } else { // Need to read super class to determine a match... try { if (match(metadata.getSuperClassName(), metadataReaderFactory)) { return true; } } catch (IOException ex) { logger.debug("Could not read super class [" + metadata.getSuperClassName() + "] of type-filtered class [" + metadata.getClassName() + "]"); } } } } if (this.considerInterfaces) { for (String ifc : metadata.getInterfaceNames()) { // Optimization to avoid creating ClassReader for super class Boolean interfaceMatch = matchInterface(ifc); if (interfaceMatch != null) { if (interfaceMatch.booleanValue()) { return true; } } else { // Need to read interface to determine a match... try { if (match(ifc, metadataReaderFactory)) { return true; } } catch (IOException ex) { logger.debug("Could not read interface [" + ifc + "] for type-filtered class [" + metadata.getClassName() + "]"); } } } } return false; }
6.11 跳转回子类进行判断
protected boolean matchSelf(MetadataReader metadataReader) { AnnotationMetadata metadata = metadataReader.getAnnotationMetadata(); return metadata.hasAnnotation(this.annotationType.getName()) || (this.considerMetaAnnotations && metadata.hasMetaAnnotation(this.annotationType.getName())); }
6.12 跳转回6.9,如果发现这个类上面有Component注解信息,那么就符合条件。对于符合条件的,就会创建一个beanDefinition对象,然后将元数据信息封装进去,并放入容器中,最后返回
6.13 跳回6.8,拿到candidates后,就会遍历处理,返回beanDefinition集合,结合6.5,然后将beanDefinition集合注册到spring容器中,这样这个context的自定义标签解析完毕。
<!--配置扫描路径样例--> <context:component-scan base-package="com.hello" />