前面跟踪了Spring框架如何解析xml模式配置的bean解析(参见“一起学SF框架系列5.7-模块Beans-BeanDefinition解析”),本文主要解析注解bean(详见“一起学SF框架系列5.2-模块Beans-bean的元数据配置”)是如何被Spring框架解析的。
注解bean的配置如下:
<context:annotation-config/>
<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。
解析非默认命名空间定义的元素。
//过渡类
@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)完成的。
根据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解析器。
查找要解析元素对应的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”;