/** * Parse the elements at the root level in the document: * "import", "alias", "bean". * @param root the DOM root element of the document */ protectedvoidparseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { if (delegate.isDefaultNamespace(root)) { NodeListnl= root.getChildNodes(); for (inti=0; i < nl.getLength(); i++) { Nodenode= nl.item(i); if (node instanceof Element) { Elementele= (Element) node; if (delegate.isDefaultNamespace(ele)) { parseDefaultElement(ele, delegate); } else { delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }
其中的 delegate.parseCustomElement(ele) 既是对自定义标签的解析
BeanDefinitionParserDelegate.parseCustomElement
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
public BeanDefinition parseCustomElement(Element ele) { return parseCustomElement(ele, null); } // containingBd 为父类 bean,对顶层元素的解析应设置为 null public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) { // 获取对应的命名空间 StringnamespaceUri= getNamespaceURI(ele); // 根据命名空间找到对应的 NamespaceHandler NamespaceHandlerhandler=this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler == null) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); returnnull; } // 调用自定义的 NamespaceHandler 进行解析 return handler.parse(ele, newParserContext(this.readerContext, this, containingBd)); }
获取标签的命名空间
直接调用 org.w3c.dom.Node 中的方法
1 2 3
public String getNamespaceURI(Node node) { return node.getNamespaceURI(); }
提取自定义标签处理器
private final XmlReaderContext readerContext 即 new ClassPathResource("beanFactory.xml")
/** * Parses the supplied {@link Element} by delegating to the {@link BeanDefinitionParser} that is * registered for that {@link Element}. */ @Override public BeanDefinition parse(Element element, ParserContext parserContext) { // 寻找解析器并进行解析操作 return findParserForElement(element, parserContext).parse(element, parserContext); } /** * Locates the {@link BeanDefinitionParser} from the register implementations using * the local name of the supplied {@link Element}. */ private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) { // 获取元素名称,也就是 <myname:user> 中的 user,若在上面的示例中,则此时 localName 为 user StringlocalName= parserContext.getDelegate().getLocalName(element); // 根据 user 找到对应的解析器,也就是在 // registerBeanDefinitionParser("user", new UserBeanDefinitionParser()) 注册的解析器 BeanDefinitionParserparser=this.parsers.get(localName); if (parser == null) { parserContext.getReaderContext().fatal( "Cannot locate BeanDefinitionParser for element [" + localName + "]", element); } return parser; }
/** * Creates a {@link BeanDefinitionBuilder} instance for the * {@link #getBeanClass bean Class} and passes it to the * {@link #doParse} strategy method. * @param element the element that is to be parsed into a single BeanDefinition * @param parserContext the object encapsulating the current state of the parsing process * @return the BeanDefinition resulting from the parsing of the supplied {@link Element} * @throws IllegalStateException if the bean {@link Class} returned from * {@link #getBeanClass(org.w3c.dom.Element)} is {@code null} * @see #doParse */ @Override protectedfinal AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { BeanDefinitionBuilderbuilder= BeanDefinitionBuilder.genericBeanDefinition(); StringparentName= getParentName(element); if (parentName != null) { builder.getRawBeanDefinition().setParentName(parentName); } // 获取自定义标签中的 class,此时会调用自定义解析器如 UserBeanDefinitionParser 中的 getBeanClass 方法 Class<?> beanClass = getBeanClass(element); if (beanClass != null) { builder.getRawBeanDefinition().setBeanClass(beanClass); } else { // 若子类没有重写 getBeanClass 方法则尝试检查子类是否重写 getBeanClassName 方法 StringbeanClassName= getBeanClassName(element); if (beanClassName != null) { builder.getRawBeanDefinition().setBeanClassName(beanClassName); } } builder.getRawBeanDefinition().setSource(parserContext.extractSource(element)); if (parserContext.isNested()) { // 若存在父类则使用父类的 scope 属性 // Inner bean definition must receive same scope as containing bean. builder.setScope(parserContext.getContainingBeanDefinition().getScope()); } if (parserContext.isDefaultLazyInit()) { // Default-lazy-init applies to custom bean definitions as well. // 配置延迟加载 builder.setLazyInit(true); } // 调用子类重写的 doParse 方法进行解析 doParse(element, parserContext, builder); return builder.getBeanDefinition(); }