Spring源码之NamespaceHandler和NamespaceHandlerSupport
程序员文章站
2022-05-21 19:26:08
...
最近看分布式平台消息队列组件源码的时候,涉及到了使用继承自NamespaceHandlerSupport的类来向spring容器中注入bean定义解析器
NamespaceHandler
直接上NamespaceHandler代码:
public interface NamespaceHandler {
/**
* 初始化向spring容器中注册bean定义解析器
*/
void init();
/**
* 解析函数
*/
BeanDefinition parse(Element var1, ParserContext var2);
BeanDefinitionHolder decorate(Node var1, BeanDefinitionHolder var2, ParserContext var3);
}
NamespaceHandlerSupport
NamespaceHandlerSupport则是NamespaceHandler的实现,但仍然是抽象类
首先它有如下变量:
private final Map<String, BeanDefinitionParser> parsers = new HashMap();
private final Map<String, BeanDefinitionDecorator> decorators = new HashMap();
private final Map<String, BeanDefinitionDecorator> attributeDecorators = new HashMap();
这三个HashMap中装的分别是:Bean定义解析器和装饰器
构造函数:
public NamespaceHandlerSupport() {}
实现父类parse函数:
public BeanDefinition parse(Element element, ParserContext parserContext) {
//调用了本地的findParserForElement函数
return this.findParserForElement(element, parserContext).parse(element, parserContext);
}
findParserForElement函数:
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
/*
* 首先根据元素element获取其localName
*/
String localName = parserContext.getDelegate().getLocalName(element);
/*
* 然后根据localName从map(parsers)中获取Bean定义解析器
*/
BeanDefinitionParser parser = (BeanDefinitionParser)this.parsers.get(localName);
if (parser == null) {
/*
* 找不到解析器则提示
*/
parserContext.getReaderContext().fatal("Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
}
return parser;
}
实现父类decorate方法和上述类似,只不过是从decorators 和 attributeDecorators中查找:
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
return this.findDecoratorForNode(node, parserContext).decorate(node, definition, parserContext);
}
private BeanDefinitionDecorator findDecoratorForNode(Node node, ParserContext parserContext) {
BeanDefinitionDecorator decorator = null;
/*
* 首先根据元素element获取其localName
*/
String localName = parserContext.getDelegate().getLocalName(node);
/**
* 判断node是Element还是Attr,再查找对应的decorator
*/
if (node instanceof Element) {
decorator = (BeanDefinitionDecorator)this.decorators.get(localName);
} else if (node instanceof Attr) {
decorator = (BeanDefinitionDecorator)this.attributeDecorators.get(localName);
} else {
parserContext.getReaderContext().fatal("Cannot decorate based on Nodes of type [" + node.getClass().getName() + "]", node);
}
if (decorator == null) {
parserContext.getReaderContext().fatal("Cannot locate BeanDefinitionDecorator for " + (node instanceof Element ? "element" : "attribute") + " [" + localName + "]", node);
}
return decorator;
}
最后是三个注册方法,分别向spring容器中注册parser,decorator,本质上是放入HashMap中:
protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) {
this.parsers.put(elementName, parser);
}
protected final void registerBeanDefinitionDecorator(String elementName, BeanDefinitionDecorator dec) {
this.decorators.put(elementName, dec);
}
protected final void registerBeanDefinitionDecoratorForAttribute(String attrName, BeanDefinitionDecorator dec) {
this.attributeDecorators.put(attrName, dec);
}
使用
写一个类继承NamespaceHandlerSupport,实现init()方法:
public class MQNamespaceHandler extends NamespaceHandlerSupport{
public void init() {
registerBeanDefinitionParser("publisher", new PublisherBeanDefinitionParser());
registerBeanDefinitionParser("subscriber", new SubscriberBeanDefinitionParser());
}
}
推荐阅读
-
Spring源码解析之ConfigurableApplicationContext
-
Spring学习之动态代理(JDK动态代理和CGLIB动态代理)
-
Mybaits 源码解析 (十一)----- 设计模式精妙使用:静态代理和动态代理结合使用:@MapperScan将Mapper接口生成代理注入到Spring
-
Mybaits 源码解析 (十二)----- Mybatis的事务如何被Spring管理?Mybatis和Spring事务中用的Connection是同一个吗?
-
spring-boot-2.0.3不一样系列之源码篇 - run方法(三)之createApplicationContext,绝对有值得你看的地方
-
Swoft源码之Swoole和Swoft的分析
-
九、Spring之BeanFactory源码分析(一)
-
Spring源码分析之IoC容器初始化
-
Volley源码之使用方式和使用场景详解
-
spring源码深度解析— IOC 之 默认标签解析(上)