spring源码-2.3.自定义标签的解析

上一节已经详细的看了一下默认标签的解析了,这一节我们来看一下自定义标签是如何解析的。
首先,来看一下自定义标签解析的入口方法,delegate.parseCustomElement(ele):

public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
    //根据标签获取其名称空间
	String namespaceUri = getNamespaceURI(ele);
	if (namespaceUri == null) {
		return null;
	}
	//通过nameSpaceUri初始化一个NamespaceHandler
	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));
}

继续进入解析标签的逻辑,handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)):

public BeanDefinition parse(Element element, ParserContext parserContext) {
    //这里根据element在handler中获取对应的解析器
	BeanDefinitionParser parser = findParserForElement(element, parserContext);
	//使用BeanDefinitionParser解析器来解析element
	return (parser != null ? parser.parse(element, parserContext) : null);
}

我这边跟代码的时候使用的自定义标签是component-scan,获取到的解析器为ComponentScanBeanDefinitionParser
继续进入解析器解析element的代码,parser.parse(element, parserContext):

public BeanDefinition parse(Element element, ParserContext parserContext) {
    //获取component-scan标签的base-package的值
	String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
	//解析basePackage的结果,如果没有${,那么直接返回,如果有,则去配置文件中解析
	basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
	//根据,;进行切割
	String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
			ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);

	// 初始化一个scanner对象,包括设置该标签中对应的属性和子标签的定义
	ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
	//扫描包,并生成对应的beanDefinition
	Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
	/**将上一步的扫描结果注册到applicationContext,并且将默认的几个beanDefinition也初始化,并注册
	* 1. ConfigurationClassPostProcessor
	* 2. AutowiredAnnotationBeanPostProcessor
	* 3. CommonAnnotationBeanPostProcessor
	* 4. EventListenerMethodProcessor
	* 5. DefaultEventListenerFactory
	* 关于这5个默认的beanDefinition,以后会做详细的介绍(例如第一个ConfigurationClassPostProcessor就是Configuration注解的实现)
	*/
	registerComponents(parserContext.getReaderContext(), beanDefinitions, element);

	return null;
}

继续进入扫描的逻辑,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注解标注的类,将解析成beanDefinition
		Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
		for (BeanDefinition candidate : candidates) {
		    //设置beanDefinition的scope属性,默认是singleton
			ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
			candidate.setScope(scopeMetadata.getScopeName());
			String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
			if (candidate instanceof AbstractBeanDefinition) {
			    //设置一些beanDefinition的默认属性,如懒加载,autowiredMode等
				postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
			}
			if (candidate instanceof AnnotatedBeanDefinition) {
			    //设置beanDefinition的其他的一些属性,如primary,depend-on,role等
				AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
			}
			//判断是否已经被注册过
			if (checkCandidate(beanName, candidate)) {
			    //没有注册
			    //将beanDefinition包装成definitionHolder
				BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
				definitionHolder =
						AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
				beanDefinitions.add(definitionHolder);
				//将definitionHolder注册到applicationContext,逻辑同默认标签的注册是一样的
				registerBeanDefinition(definitionHolder, this.registry);
			}
		}
	}
	return beanDefinitions;
}

进入findCandidateComponents(basePackage):

public Set<BeanDefinition> findCandidateComponents(String basePackage) {
	if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
		return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
	}
	else {
		return scanCandidateComponents(basePackage);
	}
}

componentsIndex是空的,所以会直接进入到else,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对象
		Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
		for (Resource resource : resources) {
			if (resource.isReadable()) {
				try {
				    //将resource对象(记录了class文件的信息)抽象成元数据对象
					MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
					//判断是否有Component注解标注
					if (isCandidateComponent(metadataReader)) {
					    //更具元数据初始化一个beanDefintion
						ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
						sbd.setResource(resource);
						sbd.setSource(resource);
						//判断是否是component标注的beanDefinition,如果是,则添加到返回结果中
						if (isCandidateComponent(sbd)) {
							candidates.add(sbd);
						}
					}
				}
				catch (Throwable ex) {
					throw new BeanDefinitionStoreException(
							"Failed to read candidate component class: " + resource, ex);
				}
			}
		}
	}
	catch (IOException ex) {
		throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
	}
	return candidates;
}

这边我们分别来看看如何判断元数据对象和beanDefinition对象是否是component标注的,isCandidateComponent(metadataReader):

protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
    //默认是空的
	for (TypeFilter tf : this.excludeFilters) {
		if (tf.match(metadataReader, getMetadataReaderFactory())) {
			return false;
		}
	}
	for (TypeFilter tf : this.includeFilters) {
	    //如果类的注解中存在component名字的注解
		if (tf.match(metadataReader, getMetadataReaderFactory())) {
		    //内部逻辑是会初始化一个conditionEvaluator(条件评估对象),判断是否需要跳过不加载
		    //就是判断是否被conditional注解标注,如果有,判断值的内容,看是否需要跳过
			return isConditionMatch(metadataReader);
		}
	}
	return false;
}

下面再来看看如何判断beanDefinition对象是否是component标注的,isCandidateComponent(sbd):

protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
	AnnotationMetadata metadata = beanDefinition.getMetadata();
	/**
	* metadata.isIndependent():不是内部类或者是静态内部类
	* metadata.isConcrete():不能是接口或抽象类
	* metadata.isAbstract():是抽象类、
	* metadata.hasAnnotatedMethods(Lookup.class.getName()):有lookUp注解标注
	* 总结就是需要满足以下两个条件:
	* 1. 不能是内部类或者是静态内部类
	* 2. 不能是接口或者抽象类,如果是抽象类,则需要LookUp注解标注
	*/
	return (metadata.isIndependent() && (metadata.isConcrete() ||
			(metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName()))));
}

至此,自定义标签的解析就已经完成了。

发布了81 篇原创文章 · 获赞 16 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/mazhen1991/article/details/100066954