参考博客:
博客1:https://juejin.im/post/5cdcda42f265da035e214b66
博客2: https://www.cnblogs.com/lxyit/p/10210581.html
在本案例中的扫描包配置如下:
待扫描的bean如下:
DefaultBeanDefinitionDocumentReader:
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
//Bean定义的Document对象使用了Spring默认的XML命名空间
if (delegate.isDefaultNamespace(root)) {
//获取Bean定义的Document对象根元素的所有子节点
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
//获得Document节点是XML元素节点
if (node instanceof Element) {
Element ele = (Element) node;
//Bean定义的Document的元素节点使用的是Spring默认的XML命名空间
if (delegate.isDefaultNamespace(ele)) {
//主线
// 这里只处理 namespace 为 http://www.springframework.org/schema/beans 的标签
parseDefaultElement(ele, delegate);
}
else {
// 用户自定义命名空间
//对自定义标签处理 会解析 <context:component-scan base-package="com.zj.scan"/> 或者自定义 dubbo等
//重点 重点 重点 注解bean的解析入口
delegate.parseCustomElement(ele); //代码1
}
}
}
}
else {
//自定义标签解析
delegate.parseCustomElement(root);
}
}
代码1将执行自定义标签的解析,其实spring自带就有大量的自定义标签,比如注解驱动<context:component-scan>
或者是<aop:advice>
等。下面将分析spring是如何来解析这些大量的自定义标签的,本文以<context:component-scan>
为例。
了解自定义标签可以参考:
https://www.cnblogs.com/mahuan2/p/7213866.html
BeanDefinitionParserDelegat
e:
public BeanDefinition parseCustomElement(Element ele) {
return parseCustomElement(ele, null);
}
调用重载方法:
BeanDefinitionParserDelegate:
@Nullable
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
//解析节点的命名空间
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
//解析命名空间,得到一个命名空间处理器
//重点
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); //代码1
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
//开始解析
//主线 重点
return handler.parse(ele, new ParserContext(