您的位置:首页 > 编程语言 > Java开发

Spring自定义标签工作原理

2018-01-11 15:19 399 查看
Spring自定义标签操作见博客:Spring自定义标签操作

基础知识:

Spring默认会将xml中所有等标签解析为BeanDefinition的抽象,自定义标签的本质是扩展Spring自身的标签,使其从自定义标签转化为BeanDefinition的过程。

核心类:

XmlBeanDefinitionReader

1.Spring Bean 注册方法:

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}


2.解析Spring XML标签元素

核心类: DefaultBeanDefinitionDocumentReader

protected void doRegisterBeanDefinitions(Element root) {

BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);

if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}

preProcessXml(root);
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);

this.delegate = parent;
}


分析:Spring将bean标签的元素委托给delegate对象处理,parseBeanDefinitions()方法将XML文件的解析转交给delegate处理

parseBeanDefinitions方法核心代码:

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {

if (delegate.isDefaultNamespace(root)) {

NodeList nl = root.getChildNodes();

for (int i = 0; i < nl.getLength(); i++) {

Node node = nl.item(i);

if (node instanceof Element) {

Element ele = (Element) node;

if (delegate.isDefaultNamespace(ele)) {

parseDefaultElement(ele, delegate);

}

else {

delegate.parseCustomElement(ele);

}

}

}

}

else {

delegate.parseCustomElement(root);

}

}

分析:

parseDefaultElement(ele, delegate):解析Spring自带的标签:例如import/alias/bean/beans

parseCustomElement : 解析自定义标签

Spring标签具体解析核心类:BeanDefinitionParserDelegate

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


分析:

NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);


通过XML命名空间(http://www.zhiwei.com/schema/user)获取命名空间解析器:

获取流程:

通过DefaultNamespaceHandlerResolver解析META-INF/spring.handlers,获取XML命令空间对应的名称空间解析器:com.zhiwei.basic.tag.NamespaceHandler,

本质通过类权限限定名通过反射机制获取自定义名称空间解析器实例

this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);

源码:

@Override
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);
}
}
}


代码分析:

NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
namespaceHandler.init();
handlerMappings.put(namespaceUri, namespaceHandler);


instantiateClass:反射机制实例化NamespaceHandler实例,然后按照自定义标签名和自定义标签解析器信息缓存到父类NamespaceHandlerSupport的parsers集合中,同时将XML名称空间及处理器存放在DefaultNamespaceHandlerResolver 的handlerMappings中,最终返回NamespaceHandler。

回到BeanDefinitionParserDelegate 的 parseCustomElement方法

代码分析

handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));


功能:之前只是获取NamespaceHandler,并进行相关的配置信息缓存空间,这行代码是最底层解析标签并注入到IOC容器的具体实现。

具体分析handler.parse方法:

这里本质调到Namespacehandler父类:NamespaceHandlerSupport方法

源码:

return findParserForElement(element, parserContext).parse(element, parserContext);


findParserForElement(element, parserContext) :从缓存中获取自定义标签解析器

parse(element, parserContext): 解析自定义标签,并注入IOC容器

具体parse方法分析:

源码:自定义解析器父类AbstractBeanDefinitionParser.parse()方法:

源码:

@Override
public final BeanDefinition parse(Element element, ParserContext parserContext) {
AbstractBeanDefinition definition = parseInternal(element, parserContext);
if (definition != null && !parserContext.isNested()) {
try {
String id = resolveId(element, definition, parserContext);
if (!StringUtils.hasText(id)) {
parserContext.getReaderContext().error(
"Id is required for element '" + parserContext.getDelegate().getLocalName(element)
+ "' when used as a top-level tag", element);
}
String[] aliases = null;
if (shouldParseNameAsAliases()) {
String name = element.getAttribute(NAME_ATTRIBUTE);
if (StringUtils.hasLength(name)) {
aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name));
}
}
BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases);
registerBeanDefinition(holder, parserContext.getRegistry());
if (shouldFireEvents()) {
BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder);
postProcessComponentDefinition(componentDefinition);
parserContext.registerComponent(componentDefinition);
}
}
catch (BeanDefinitionStoreException ex) {
parserContext.getReaderContext().error(ex.getMessage(), element);
return null;
}
}
return definition;
}


代码分析:

AbstractBeanDefinition definition = parseInternal(element, parserContext);


分析:生成自定标签对应的BeanDefinition抽象,主要是调用父类AbstractSingleBeanDefinitionParser的parseInternal方法,方法内部调用我们自定义标签解析器的doParse(element, parserContext, builder);方法,实现自定义标签的处理,支持自定义标签的解析过程已经结束。

自定义标签BeanDefinition注入IOC容器

具体代码:

registerBeanDefinition(holder, parserContext.getRegistry());


主要是通过parserContext内部的readerContext成员的getRegistry()方法获取IOC容器,然后进行实质的Bean注入。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息