曹工说Spring Boot源码(7)-- Spring解析xml文件,到底从中得到了什么(上) (5)

我们先通过其实现的接口,来了解其核心功能:

package org.springframework.beans.factory.xml; import org.w3c.dom.Element; import org.springframework.beans.factory.config.BeanDefinition; /** * 该接口主要被DefaultBeanDefinitionDocumentReader使用,来处理顶级的,非默认命名空间下的的顶级元素(直接在<beans></beans>下) * Interface used by the {@link DefaultBeanDefinitionDocumentReader} to handle custom, * top-level (directly under {@code <beans/>}) tags. * * 实现类可以自由地通过该元素中的元数据,来转换为任意多个BeanDefinition。(比如<context:component-scan></>) * <p>Implementations are free to turn the metadata in the custom tag into as many * {@link BeanDefinition BeanDefinitions} as required. * * Dom解析器,通过元素所在的命名空间,找到对应的NamespaceHandler,再从NamespaceHandler中找到对应的BeanDefinitionParser * <p>The parser locates a {@link BeanDefinitionParser} from the associated * {@link NamespaceHandler} for the namespace in which the custom tag resides. * * @author Rob Harrop * @since 2.0 * @see NamespaceHandler * @see AbstractBeanDefinitionParser */ public interface BeanDefinitionParser { /** * 解析指定的element,注册其返回的BeanDefinition到BeanDefinitionRegistry * (使用参数ParserContext#getRegistry()得到BeanDefinitionRegistry) */ BeanDefinition parse(Element element, ParserContext parserContext); }

大家发现接口的意义了吗,虽然前面的类,很复杂,但我们通过接口,可以马上知道其核心功能。在这里,就是解析元素,获得BeanDefinition。

其实,到这里,基本可以回答,标题所提出的问题了,Spring解析xml,得到了什么?

从这个接口,可以知道,得到了BeanDefinition!

UtilNamespaceHandler.ConstantBeanDefinitionParser

我们具体看看解析过程,这个类没有直接实现parse方法,是在其父类实现的:

AbstractBeanDefinitionParser#parse public final BeanDefinition parse(Element element, ParserContext parserContext) { // 这个方法就是个骨架,用了模板方法设计模式, // 1:调用另一个方法,获取BeanDefinition AbstractBeanDefinition definition = parseInternal(element, parserContext); if (definition != null && !parserContext.isNested()) { // 2:获得id String id = resolveId(element, definition, parserContext); // 3:获得别名 String name = element.getAttribute(NAME_ATTRIBUTE); String[] aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name)); // 4:将beanDefinition的id、别名、definition等放进一个holder类 BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases); // 5:通过parserContext,得到BeanDefinitionRegistry,注册本bean进去 registerBeanDefinition(holder, parserContext.getRegistry()); if (shouldFireEvents()) { BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder); postProcessComponentDefinition(componentDefinition); parserContext.registerComponent(componentDefinition); } } return definition; }

我们上面,第一步的注释那里,说用了模板设计模式,因为这个parseInternal是个抽象方法:

protected abstract AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext);

具体的实现,还在子类,鉴于这个类的层次有点深,我们再看看类图:

曹工说Spring Boot源码(7)-- Spring解析xml文件,到底从中得到了什么(上)

这个parseInternal就在`AbstractSingleBeanDefinitionParser:

// 这个方法也足够简单,就是构造一个BeanDefinition,用了builder设计模式。 protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(); String parentName = getParentName(element); // ConstantBeanDefinitionParser覆盖了这个方法 Class<?> beanClass = getBeanClass(element); if (beanClass != null) { builder.getRawBeanDefinition().setBeanClass(beanClass); } else { String beanClassName = getBeanClassName(element); if (beanClassName != null) { builder.getRawBeanDefinition().setBeanClassName(beanClassName); } } builder.getRawBeanDefinition().setSource(parserContext.extractSource(element)); if (parserContext.isDefaultLazyInit()) { // Default-lazy-init applies to custom bean definitions as well. builder.setLazyInit(true); } // 子类.AbstractSimpleBeanDefinitionParser重写了这个方法 doParse(element, parserContext, builder); return builder.getBeanDefinition(); }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpfszg.html