SpringIOC-自定义标签解析
自定义标签解析流程
parseCustomElement
接着上文parseCustomElement是自定义标签解析的入口
使用了Spring的SPI发现思想,从标签元素获取URI,接着从spring.handlers获取对应的解析类进行操作 具体流程可以参考《命名空间解析》
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Nullable public BeanDefinition parseCustomElement (Element ele, @Nullable BeanDefinition containingBd) { String namespaceUri = getNamespaceURI(ele); if (namespaceUri == null ) { return null ; } 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)); }
我们构建 XmlReaderContext 时会创建一个默认的DefaultNamespaceHandlerResolver,这边拿到的就是当时创建的 DefaultNamespaceHandlerResolver 对象,例如下图。
在进行resolve获取NamespaceHandler的时候会调用NamespaceHandler.init 方法进行解析类的初始化注册
我们就拿context标签来举例,其他的都一样根据spring.handlers的配置,会调用到ContextNamespaceHandler的init方法
我们接下来就以最重要也是最常用的component-scan 包扫描来讲解下具体流程,
1 registerBeanDefinitionParser("component-scan" , new ComponentScanBeanDefinitionParser ());
我们发现核心解析类是ComponentScanBeanDefinitionParser
DefaultNamespaceHandlerResolver.resolve
根据URI获取对那个的NamespaceHandler
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 @Override @Nullable public NamespaceHandler resolve (String namespaceUri) { Map<String, Object> handlerMappings = getHandlerMappings(); Object handlerOrClassName = handlerMappings.get(namespaceUri); if (handlerOrClassName == null ) { return null ; } else if (handlerOrClassName instanceof NamespaceHandler) { return (NamespaceHandler) handlerOrClassName; } 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); namespaceHandler.init(); handlerMappings.put(namespaceUri, namespaceHandler); return namespaceHandler; } catch (ClassNotFoundException ex) { throw new FatalBeanException ("Could not find NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]" , ex); } catch (LinkageError err) { throw new FatalBeanException ("Unresolvable class definition for NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]" , err); } } }
getHandlerMappings
获取所有的 URI和NamespaceHandler的映射关系
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 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 { Properties mappings = PropertiesLoaderUtils.loadAllProperties(this .handlerMappingsLocation, this .classLoader); if (logger.isTraceEnabled()) { logger.trace("Loaded NamespaceHandler mappings: " + mappings); } 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; }
我们知道 handlerMappingsLocation 的默认值为 “META-INF/spring.handlers”,因此在这边会使用指定的 classLoader 从所有类路径资源(META-INF/spring.handlers)加载所有属性,并使用 Properties 来存放 spring.handlers 文件中的内容(命名空间和 handler 的键值对,例如下图)。
2.2 将 Properties 转成 Map。其中 key 为命名空间,例如:http://www.springframework.org/schema/context;value 为命名空间对应的 handler,例如:org.springframework.context.config.ContextNamespaceHandler,所有的handler都需要自己实现。
2.3 最后将转换后的 handlerMappings 放到缓存。
namespaceHandler#init
点击该方法,我们可以看到有很多个实现类,分别对应了不同的命名空间 Handler。
我们拿最常见的命名空间:http://www.springframework.org/schema/context 来举例,对应的 handler 为 ContextNamespaceHandler。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 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 ()); } }
内容很简单,就是给 context 命名空间下的不同节点指定了不同的 BeanDefinition 解析器,并将节点名和对应的解析器注册到缓存中,见代码块4详解。例如,最常用的 component-scan 对应 ComponentScanBeanDefinitionParser 。
registerBeanDefinitionParser 1 2 3 4 5 6 7 8 9 10 private final Map<String, BeanDefinitionParser> parsers = new HashMap <String, BeanDefinitionParser>(); protected final void registerBeanDefinitionParser (String elementName, BeanDefinitionParser parser) { this .parsers.put(elementName, parser); }
将节点名和对应的解析器放到 parsers 缓存中。
2.使用拿到的 BeanDefinition 解析器解析 element 节点。例如:使用 ComponentScanBeanDefinitionParser 解析器解析 component-scan 节点。
到此为此,自定义命名空间的解析操作基本完成,只剩下具体解析器解析对应节点的内容没有写。
自定义命名空间节点常见的有:<context:component-scan />、<context:annotation-config />、aop:aspectj-autoproxy/ 、<tx:annotation-driven /> 等
parse
调用ContextNamespaceHandler 的parse方法进行解析
首先会找到对应的component-scan 元素的解析类ComponentScanBeanDefinitionParser进行元素解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 @Override @Nullable public BeanDefinition parse (Element element, ParserContext parserContext) { BeanDefinitionParser parser = findParserForElement(element, parserContext); return (parser != null ? parser.parse(element, parserContext) : null ); } @Nullable private BeanDefinitionParser findParserForElement (Element element, ParserContext parserContext) { String localName = parserContext.getDelegate().getLocalName(element); BeanDefinitionParser parser = this .parsers.get(localName); if (parser == null ) { parserContext.getReaderContext().fatal( "Cannot locate BeanDefinitionParser for element [" + localName + "]" , element); } return parser; }
1.从 parsers 缓存中(见代码块4 ),查找 element 节点对应的 BeanDefinition 解析器。parsers缓存如下:
ComponentScanBeanDefinitionParser.parse
调用ComponentScanBeanDefinitionParser的parse完成component-scan 标签的解析
<context:component-scan base-package=”com.test”/>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 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); ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages); registerComponents(parserContext.getReaderContext(), beanDefinitions, element); return null ; }
创建以及配置扫描器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 protected ClassPathBeanDefinitionScanner configureScanner (ParserContext parserContext, Element element) { boolean useDefaultFilters = true ; if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) { useDefaultFilters = Boolean.parseBoolean(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)); } 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; }
createScanner
创建扫描器
这里面注意一下 将上面的
boolean useDefaultFilters = true;
使用默认扫描器传过去了
1 2 3 4 5 6 7 8 9 10 11 protected ClassPathBeanDefinitionScanner createScanner (XmlReaderContext readerContext, boolean useDefaultFilters) { return new ClassPathBeanDefinitionScanner (readerContext.getRegistry(), useDefaultFilters, readerContext.getEnvironment(), readerContext.getResourceLoader()); }
ClassPathBeanDefinitionScanner
创建扫描器是创建一个ClassPathBeanDefinitionScanner的实例,首先看一下构造方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 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); }
registerDefaultFilters
这个方法很关键,向全局的includeFilters注册了@Component注解,代表着扫描器需要扫描@Component的注解
但是@Service,@Repository,@Controller 都继承了@Component注解所以,这些注解都会被扫描到。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @SuppressWarnings("unchecked") 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) { } 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) { } }
这边会尝试添加3个 AnnotationTypeFilter 到 includeFilters 中,但是默认情况下,添加 @Named 注解对应的 AnnotationTypeFilter 时会抛异常。因此,执行完该方法,includeFilters 会有两个 AnnotationTypeFilter,分别对应 @Component 注解和 @ManagedBean 注解,如下图所示。
parseTypeFilters 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 protected void parseTypeFilters (Element element, ClassPathBeanDefinitionScanner scanner, ParserContext parserContext) { ClassLoader classLoader = scanner.getResourceLoader().getClassLoader(); NodeList nodeList = element.getChildNodes(); for (int i = 0 ; i < nodeList.getLength(); i++) { Node node = nodeList.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { String localName = parserContext.getDelegate().getLocalName(node); try { if (INCLUDE_FILTER_ELEMENT.equals(localName)) { TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext); scanner.addIncludeFilter(typeFilter); } else if (EXCLUDE_FILTER_ELEMENT.equals(localName)) { TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext); scanner.addExcludeFilter(typeFilter); } } catch (ClassNotFoundException ex) { parserContext.getReaderContext().warning( "Ignoring non-present type filter class: " + ex, parserContext.extractSource(element)); } catch (Exception ex) { parserContext.getReaderContext().error( ex.getMessage(), parserContext.extractSource(element), ex.getCause()); } } } } @SuppressWarnings("unchecked") protected TypeFilter createTypeFilter (Element element, @Nullable ClassLoader classLoader, ParserContext parserContext) throws ClassNotFoundException { String filterType = element.getAttribute(FILTER_TYPE_ATTRIBUTE); String expression = element.getAttribute(FILTER_EXPRESSION_ATTRIBUTE); expression = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(expression); if ("annotation" .equals(filterType)) { return new AnnotationTypeFilter ((Class<Annotation>) ClassUtils.forName(expression, classLoader)); } else if ("assignable" .equals(filterType)) { return new AssignableTypeFilter (ClassUtils.forName(expression, classLoader)); } else if ("aspectj" .equals(filterType)) { return new AspectJTypeFilter (expression, classLoader); } else if ("regex" .equals(filterType)) { return new RegexPatternTypeFilter (Pattern.compile(expression)); } else if ("custom" .equals(filterType)) { Class<?> filterClass = ClassUtils.forName(expression, classLoader); if (!TypeFilter.class.isAssignableFrom(filterClass)) { throw new IllegalArgumentException ( "Class is not assignable to [" + TypeFilter.class.getName() + "]: " + expression); } return (TypeFilter) BeanUtils.instantiateClass(filterClass); } else { throw new IllegalArgumentException ("Unsupported filter type: " + filterType); } }
我们知道,当我们配置了 component-scan 时,Spring会去扫描 base-package 下所有使用了 @Component(包括@Controller、@Repository、@Service) 注解的 bean。这是因为 use-default-filters 属性默认值为 true,而通过代码块registerDefaultFilters我们知道,use-default-filters = true 时,includeFilters 会有两个 AnnotationTypeFilter,分别对应 @Component 注解和 @ManagedBean 注解。
如果我们想排除掉使用了 @Controller 注解的 bean 时,就可以使用 exclude-filter 属性,例如以下配置。
1 2 3 <context:component-scan base-package ="com.test.spring.demo" > <context:exclude-filter type ="annotation" expression ="org.springframework.stereotype.Controller" /> </context:component-scan >
小结
主要完成对扫描器的创建和配置
主要流程如下
创建ClassPathBeanDefinitionScanner扫描器,并且使用使用默认的过滤器
默认过滤器将@Component注解注册到includeFilters
doScan
扫描的核心方法,完成将扫描到的class转换为BeanDefinition
主要步骤如下扫描class生成BeanDefinition
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 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) { 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); registerBeanDefinition(definitionHolder, this .registry); } } } return beanDefinitions; }
findCandidateComponents
根据classpath 扫描路径 并将类转换为BeanDefinition
1 2 3 4 5 6 7 8 9 10 11 12 13 public Set<BeanDefinition> findCandidateComponents (String basePackage) { if (this .componentsIndex != null && indexSupportsIncludeFilters()) { return addCandidateComponentsFromIndex(this .componentsIndex, basePackage); } else { return scanCandidateComponents(basePackage); } }
scanCandidateComponents
扫描符合条件的class并生成BeanDefinition
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 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; }
来到SimpleMetadataReaderFactory类
主要作用是创建SimpleMetadataReader类,并对Resources进行注解的搜集
1 2 3 4 5 6 7 8 9 10 @Override public MetadataReader getMetadataReader (Resource resource) throws IOException { return new SimpleMetadataReader (resource, this .resourceLoader.getClassLoader()); }
该类是创建一个元数据读取对象,主要的任务就是收集注解信息
1 2 3 4 5 6 7 8 9 10 11 12 13 SimpleMetadataReader(Resource resource, @Nullable ClassLoader classLoader) throws IOException { SimpleAnnotationMetadataReadingVisitor visitor = new SimpleAnnotationMetadataReadingVisitor (classLoader); getClassReader(resource).accept(visitor, PARSING_OPTIONS); this .resource = resource; this .annotationMetadata = visitor.getMetadata(); }
isCandidateComponent
该方法是对includeFilters以及excludeFilters的处理
我们在上面registerDefaultFilters方法中将@Component注解注册到了includeFilters中所以
根据传过来的元数据信息如果有@Service,@Repository,@Controller,@Component任意一个注解就会返回true,接着就会被封装到BeanDefinition中返回
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 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 ; }
这边的 excludeFilters 和 includeFilters 在上面的代码块3、代码块4中已经介绍过。默认情况下 excludeFilters 为空,includeFilters 包含:@Component 注解的 TypeFilter、@ManagedBean 注解的 TypeFilter。
因此,在正常情况下,使用了 @Component(包括被 @Component 修饰的 @Controller、@Repository、@Service) 注解的类在这边会返回 true,表示该类是候选者类。
isCandidateComponent
校验bean不是接口 不是抽象类,没有Lookup注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 protected boolean isCandidateComponent (AnnotatedBeanDefinition beanDefinition) { AnnotationMetadata metadata = beanDefinition.getMetadata(); return (metadata.isIndependent() && (metadata.isConcrete() || (metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName())))); }
正常使用,在前两个条件校验完就会返回 true,不会走到后面两个条件。
小结
findCandidateComponents方法主要完成了根据路径找到对应的class并封装成BeanDefinition
步骤如下
生成包的扫描路径
递归的方式找到basepackage下的所有的class文件,并包装成Resource
收集Resource文件的注解,并将Resource的注解包装为MetadataReader
通过includeFilters和excludeFilters对MetadataReader进行过滤,因为默认includeFilters有@Component的注解所有会将@Service,@Repository,@Controller,@Component等注解的类筛选出来
筛选出来的类创建BeanDefinition
校验bean不是接口 不是抽象类,没有Lookup注解
添加到BeanDefinition的集合中返回
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @Override public ScopeMetadata resolveScopeMetadata (BeanDefinition definition) { ScopeMetadata metadata = new ScopeMetadata (); if (definition instanceof AnnotatedBeanDefinition) { AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition; AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor( annDef.getMetadata(), this .scopeAnnotationType); if (attributes != null ) { metadata.setScopeName(attributes.getString("value" )); ScopedProxyMode proxyMode = attributes.getEnum("proxyMode" ); if (proxyMode == ScopedProxyMode.DEFAULT) { proxyMode = this .defaultProxyMode; } metadata.setScopedProxyMode(proxyMode); } } return metadata; }
如果使用了@Scope注解,则解析注解的属性。这边的 defaultProxyMode 取决于代码块1中步骤5的 scope-resolver、scoped-proxy 属性,默认为 ScopedProxyMode.NO。可以通过 scoped-proxy 来设置,例如下面配置 defaultProxyMode 的值就为 ScopedProxyMode.TARGET_CLASS。
1 2 3 <context:component-scan base-package ="com.test.spring.demo" scoped-proxy ="targetClass" > <context:exclude-filter type ="annotation" expression ="org.springframework.stereotype.Controller" /> </context:component-scan >
postProcessBeanDefinition
进一步处理BeanDefinition对象
1 2 3 4 5 6 7 8 protected void postProcessBeanDefinition (AbstractBeanDefinition beanDefinition, String beanName) { beanDefinition.applyDefaults(this .beanDefinitionDefaults); if (this .autowireCandidatePatterns != null ) { beanDefinition.setAutowireCandidate(PatternMatchUtils.simpleMatch(this .autowireCandidatePatterns, beanName)); } }
processCommonDefinitionAnnotations
该方法是对公共注解的解析,将公共注解设置进BeanDefinition
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 public static void processCommonDefinitionAnnotations (AnnotatedBeanDefinition abd) { processCommonDefinitionAnnotations(abd, abd.getMetadata()); } static void processCommonDefinitionAnnotations (AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) { AnnotationAttributes lazy = attributesFor(metadata, Lazy.class); if (lazy != null ) { abd.setLazyInit(lazy.getBoolean("value" )); } else if (abd.getMetadata() != metadata) { lazy = attributesFor(abd.getMetadata(), Lazy.class); if (lazy != null ) { abd.setLazyInit(lazy.getBoolean("value" )); } } if (metadata.isAnnotated(Primary.class.getName())) { abd.setPrimary(true ); } AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class); if (dependsOn != null ) { abd.setDependsOn(dependsOn.getStringArray("value" )); } AnnotationAttributes role = attributesFor(metadata, Role.class); if (role != null ) { abd.setRole(role.getNumber("value" ).intValue()); } AnnotationAttributes description = attributesFor(metadata, Description.class); if (description != null ) { abd.setDescription(description.getString("value" )); } }
checkCandidate
对beanDefinition 进行检查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 protected boolean checkCandidate (String beanName, BeanDefinition beanDefinition) throws IllegalStateException { if (!this .registry.containsBeanDefinition(beanName)) { return true ; } BeanDefinition existingDef = this .registry.getBeanDefinition(beanName); BeanDefinition originatingDef = existingDef.getOriginatingBeanDefinition(); if (originatingDef != null ) { existingDef = originatingDef; } if (isCompatible(beanDefinition, existingDef)) { return false ; } throw new ConflictingBeanDefinitionException ("Annotation-specified bean name '" + beanName + "' for bean class [" + beanDefinition.getBeanClassName() + "] conflicts with existing, " + "non-compatible bean definition of same name and class [" + existingDef.getBeanClassName() + "]" ); }
applyScopedProxyMode
根据proxyMode的值,选择是否创建作用域代理
1 2 3 4 5 6 7 8 9 10 11 12 13 static BeanDefinitionHolder applyScopedProxyMode ( ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) { ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode(); if (scopedProxyMode.equals(ScopedProxyMode.NO)) { return definition; } boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS); return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass); }
createScopedProxy
创建动态代理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 public static BeanDefinitionHolder createScopedProxy ( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry, boolean proxyTargetClass) { return ScopedProxyUtils.createScopedProxy(definitionHolder, registry, proxyTargetClass); } public static BeanDefinitionHolder createScopedProxy (BeanDefinitionHolder definition, BeanDefinitionRegistry registry, boolean proxyTargetClass) { String originalBeanName = definition.getBeanName(); BeanDefinition targetDefinition = definition.getBeanDefinition(); String targetBeanName = getTargetBeanName(originalBeanName); RootBeanDefinition proxyDefinition = new RootBeanDefinition (ScopedProxyFactoryBean.class); proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder (targetDefinition, targetBeanName)); proxyDefinition.setOriginatingBeanDefinition(targetDefinition); proxyDefinition.setSource(definition.getSource()); proxyDefinition.setRole(targetDefinition.getRole()); proxyDefinition.getPropertyValues().add("targetBeanName" , targetBeanName); if (proxyTargetClass) { targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE); } else { proxyDefinition.getPropertyValues().add("proxyTargetClass" , Boolean.FALSE); } proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate()); proxyDefinition.setPrimary(targetDefinition.isPrimary()); if (targetDefinition instanceof AbstractBeanDefinition) { proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition); } targetDefinition.setAutowireCandidate(false ); targetDefinition.setPrimary(false ); registry.registerBeanDefinition(targetBeanName, targetDefinition); return new BeanDefinitionHolder (proxyDefinition, originalBeanName, definition.getAliases()); }
registerBeanDefinition
该方法是最后一步,完成完善后的BeanDefinition的注册
1 2 3 4 5 6 7 protected void registerBeanDefinition (BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) { BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry); }
小结
因为返回的BeanDefinition是一个扫描的BeanDefinition,只有一个MetadataReader的封装,需要将MetadataReader的数解析到BeanDefinition的各个属性中
具体流程如下
将MetadataReader转换为ScopeMetadata获取Scope属性完成Scope的设置
生成beanName
完成公共属性的设置
对BeanDefinition做一些检查然后封装为definitionHolder
完成BeanDefinition的注册
registerComponents
注册需要进行处理的组件如 @Configuration,@Autowired等注解的处理类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 protected void registerComponents ( XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) { Object source = readerContext.extractSource(element); CompositeComponentDefinition compositeDef = new CompositeComponentDefinition (element.getTagName(), source); for (BeanDefinitionHolder beanDefHolder : beanDefinitions) { compositeDef.addNestedComponent(new BeanComponentDefinition (beanDefHolder)); } boolean annotationConfig = true ; if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) { annotationConfig = Boolean.parseBoolean(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE)); } if (annotationConfig) { Set<BeanDefinitionHolder> processorDefinitions = AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source); for (BeanDefinitionHolder processorDefinition : processorDefinitions) { compositeDef.addNestedComponent(new BeanComponentDefinition (processorDefinition)); } } readerContext.fireComponentRegistered(compositeDef); }
registerAnnotationConfigProcessors
如果annotation-config属性值为true,在给定的注册表中注册所有用于注解的Bean后置处理器
这里稍微看一下,注册了几个比较重要的BeanPostProcessor类
AutowiredAnnotationBeanPostProcessor
ConfigurationClassPostProcessor
CommonAnnotationBeanPostProcessor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors ( BeanDefinitionRegistry registry, @Nullable Object source) { DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry); if (beanFactory != null ) { if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) { beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); } if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) { beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver ()); } } Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet <>(8 ); if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition (ConfigurationClassPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); } if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition (AutowiredAnnotationBeanPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition (CommonAnnotationBeanPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)); } if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition (); try { def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, AnnotationConfigUtils.class.getClassLoader())); } catch (ClassNotFoundException ex) { throw new IllegalStateException ( "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex); } def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)); } if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition (EventListenerMethodProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME)); } if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition (DefaultEventListenerFactory.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME)); } return beanDefs; }
registerPostProcessor
注册PostProcessor
1 2 3 4 5 6 7 8 9 10 11 12 13 private static BeanDefinitionHolder registerPostProcessor ( BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) { definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(beanName, definition); return new BeanDefinitionHolder (definition, beanName); }
至此,context:component-scan 节点解析已经完成,主要做的事情有:
扫描 base-package 目录,将使用了 @Component、@Controller、@Repository、@Service 注解的 bean 注册到注册表中(其实就是beanDefinitionMap、beanDefinitionNames、aliasMap缓存中),跟之前解析默认命名空间一样,也是在后续创建 bean 时需要使用这些缓存。 添加了几个内部的注解相关的后置处理器:
ConfigurationClassPostProcessor
AutowiredAnnotationBeanPostProcessor
RequiredAnnotationBeanPostProcessor
总结 同时,本文的结束,也标志着 obtainFreshBeanFactory 方法的详解正式结束。
简单来说,有以下几个主要操作:
根据 spring.xml 中 contextConfigLocation 配置的路径,读取 Spring 配置文件,并封装成 Resource。
根据 Resource 加载 XML 配置文件,并解析成 Document 对象 。
拿到 Document 中的根节点,遍历根节点和所有子节点。
根据命名空间,进行不同的解析,将 bean 节点内容解析成 BeanDefinition。
将 BeanDefinition 注册到注册表中(也就是beanDefinitionMap、beanDefinitionNames、aliasMap缓存)。
执行完 obtainFreshBeanFactory 方法,我们得到了三个重要的对象:
新的 BeanFactory。
beanDefinitionNames 缓存。
beanDefinitionMap 缓存。
这三个对象在之后的 IoC 构建过程中会发挥重要的作用。