一起学SF框架系列5.8-spring-Beans-注解bean解析1-解析入口

前面跟踪了Spring框架如何解析xml模式配置的bean解析(参见“一起学SF框架系列5.7-模块Beans-BeanDefinition解析”),本文主要解析注解bean(详见“一起学SF框架系列5.2-模块Beans-bean的元数据配置”)是如何被Spring框架解析的。

注解配置

注解bean的配置如下:

	<!-- 配置注解模式 -->
	<context:annotation-config/>
	<!-- 注解模式:配置bean扫描路径 -->
	<context:component-scan base-package="com.learnsf.main,com.learnsf.service,com.learnsf.demo"/>

解析入口

注解解析起点在DefaultBeanDefinitionDocumentReader.parseBeanDefinitions,如下图:
在这里插入图片描述
其中xml解析是方法parseDefaultElement(ele, delegate)。
入口的前面流程参见“一起学SF框架系列5.7-模块Beans-BeanDefinition解析

解析过程

在这里插入图片描述
注:NamespaceHandlerSupport 根据不同 Namespace选择不同的解析器。SF中有如下NamespaceHandler:
在这里插入图片描述
注解bean用到的命名空间为“context",对应的NamespaceHandler是ContextNamespaceHandler。

代码跟踪

BeanDefinitionParserDelegate.parseCustomElement(Element ele)

解析非默认命名空间定义的元素。

	//过渡类
	@Nullable
	public BeanDefinition parseCustomElement(Element ele) {
		return parseCustomElement(ele, null);
	}

	// 解析一个非默认命名空间定义的元素
	@Nullable
	public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
		// 获取命名空间资源符
		String namespaceUri = getNamespaceURI(ele);
		if (namespaceUri == null) {
			return null;
		}
		// 根据命名空间资源符获得对应的解析器 注1
		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));
	}

注1:根据namespaceUri解析出用到的NamespaceHandler,不同的命名空间对应不同的NamespaceHandler。如何找到正确的NamespaceHandler则是通过NamespaceHandlerResolver(DefaultNamespaceHandlerResolver)完成的。

DefaultNamespaceHandlerResolver.resolve(String namespaceUri)

根据namespaceUri解析出用到的NamespaceHandler。

	@Override
	@Nullable
	public NamespaceHandler resolve(String namespaceUri) {
		// 根据namespaceUri从缓存获取handler
		Map<String, Object> handlerMappings = getHandlerMappings();
		Object handlerOrClassName = handlerMappings.get(namespaceUri);
		if (handlerOrClassName == null) {
			// 没有对应的handler
			return null;
		}
		else if (handlerOrClassName instanceof NamespaceHandler namespaceHandler) {
			// 如果handler是NamespaceHandler,直接返回
			return namespaceHandler;
		}
		else {
			/* 如果handler不是NamespaceHandler(则是NamespaceHandler的className),则生成 */
			String className = (String) handlerOrClassName;
			try {
				// 加载NamespaceHandler Class
				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初始化 注1
				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);
			}
		}
	}

注1:本处的NamespaceHandler是ContextNamespaceHandler,代码如下:

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());
	}

}

代码可看出,ContextNamespaceHandler 继承于NamespaceHandlerSupport ,只多提供了init()方法,用于注册该命名空间支持的各种元素BeanDefinition解析器。

NamespaceHandlerSupport.parse(Element element, ParserContext parserContext)

查找要解析元素对应的BeanDefinitionParser解析器。
从前面ContextNamespaceHandler.init()可看出:
元素annotation-config对应AnnotationConfigBeanDefinitionParser
元素component-scan对应ComponentScanBeanDefinitionParser

	@Override
	@Nullable
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		// 找元素对应的解析器:BeanDefinitionParser 
		BeanDefinitionParser parser = findParserForElement(element, parserContext);
		// 根据元素解析bean 注1
		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:不同元素可能对应不同的解析器,如:
元素context:annotation-config对应AnnotationConfigBeanDefinitionParser,具体如何解析见“一起学SF框架系列5.8-模块Beans-注解bean解析2-解析annotation-config”;
元素context:component-scan对应ComponentScanBeanDefinitionParser,具体如何解析见“一起学SF框架系列5.8-模块Beans-Bean注解解析3-解析component-scan”;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乐享技术

每一个打赏,都是对我最大的鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值