上一节说完解析默认标签,以及默认标签中的自定义标签(在默认标签中的自定义标签使用的另一种解析方式),现在解析开始的bean中自定义标签解析:
DefaultBeanDefinitionDocumentReader类的 parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) 方法中的:
delegate.parseCustomElement(ele);
1.parseCustomElement(Element ele, BeanDefinition containingBd)
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
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));
}
该类的功能有:
获取命名空间:getNamespaceURI(ele);
找到对应的命名空间处理器:this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
标签解析:handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
resolve(namespaceUri)
这里resolve的调用使用后缀的方式调用,getNamespaceHandlerResolver()返回NamespaceHandlerResolver类的实例,NamespaceHandlerResolver是一个接口,它的实现类有DefaultNamespaceHandlerResolver,所以这里resove方法的调用者是DefaultNamespaceHandlerResolver实例;
resolve方法:
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("NamespaceHandler class [" + className + "] for namespace [" +
namespaceUri + "] not found", ex);
}
catch (LinkageError err) {
throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" +
namespaceUri + "]: problem with handler class file or dependent class", err);
}
}
}
具体执行有:获取Handler映射,根据namespace找到对应的信息,判断对应的handler是否加载过,如果加载过,直接从缓存中返回,如果没有,则实现反射创建对象,然后初始化对象,然后将对象记录到缓存中。
注意这里:命名空间以及命名空间处理器的对应关系是在使用自定义标签时,配置的Spring.handlers文件中;
初始化方法会去执行BeanDefinitionParser的注册,这个方法的实现需要在自定义标签前,需要自行配置;
这里的getHandlerMappings主要是读取Spring.handlers配置文件并将配置文件缓存到map中。
handler.parse(ele, new ParserContext(this.readerContext, this, containingBd))
进入NamespaceHandlerSupport的parse方法:
public BeanDefinition parse(Element element, ParserContext parserContext) { return findParserForElement(element, parserContext).parse(element, parserContext);}
findParserForElement:
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;
}
findParserForElement返回BeanDefinitionParser实例,AbstractBeanDefinitionParser实现BeanDefinitionParser接口。
parse(element, parserContext):
public final BeanDefinition parse(Element element, ParserContext parserContext) {
AbstractBeanDefinition definition = parseInternal(element, parserContext);
......
}
return definition;
}
主要解析则使用parseInternal(element,parserContext);然后获取解析后的definition实例,然后获取id,别名,并进行注册。parseInternal()是BeanDefinitionParser接口定义的方法,BeanDefinitionParser的实现类是AbstractBeanDefinitionParser抽象类,而对于parseInternal具体的实现则使用继承AbstractBeanDefinitionParser的AbstractSingleBeanDefinitionParser实例。
parseInternal(element,parserContext)
protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
String parentName = getParentName(element);
if (parentName != null) {
builder.getRawBeanDefinition().setParentName(parentName);
}
Class<?> beanClass = getBeanClass(element);
......
doParse(element, parserContext, builder);
return builder.getBeanDefinition();
}
该方法实现的功能有:获取自定义标签中的class,获取父类中的scope属性,配置延迟加载,调用子类重写doParse方法。
补充:
对于自定义标签的配置参考 https://blog.csdn.net/wkztselina/article/details/82765949 博客,详细的介绍了如何在spring中配置自定义标签。
参考《Spring源码深度解析》
如有问题,敬请指出,与君共勉