Spring源码解析之一 解析配置以及注册Bean

Spring是一个开放源代码的设计层面框架, 解决的是业务逻辑层和其他各层的松耦合问题, 因此它将面向接口的编程思想贯穿整个系统应用.

1. XmlBeanDefinitionReader介绍

XML配置文件的读取与解析是Spring中比较重要的功能, 因为Spring的大部分功能都是以配置作为切入点, 可以从XmlBeanDefinitionReader中梳理下资源读取、解析以及注册的大致脉络.

  • ResourceLoader: 定义资源加载器, 主要应用于根据给定的资源文件地址返回对应的Resource.
  • BeanDefinitionReader: 主要定义资源文件读取并转换为BeanDefinition的各个功能.
  • EnvironmentCapable: 定义获取Environment方法.
  • DocumentLoader: 定义从资源文件加载到转换为Document的功能.
  • AbstractBeanDefinitionReader: 对EnvironmentCapable、BeanDefinitionReader类定义的功能进行实现.
  • BeanDefinitionDocumentReader: 定义读取Document并注册BeanDefinition功能.
  • BeanDefinitionParserDelegate: 定义解析Element的各种方法.

2. 代码解析

2.1 加载配置文件

了解了几个核心类之后, 我们来分析下XmlBeanFactory. 虽然该类被标注@Deprecated, 但该类是了解XmlBeanDefinitionReader的最佳途径, 其内部直接持有XmlBeanDefinitionReader对象用来解析XML配置.

public class XmlBeanFactory extends DefaultListableBeanFactory {

    private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);

    public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
        super(parentBeanFactory);
        // 此处才是资源加载的真正实现.
        this.reader.loadBeanDefinitions(resource);
    }
}

在分析this.reader.loadBeanDefinitions(resource)方法前, 先看下super()中的代码, 此处直接追踪到父类AbstractAutowireCapableBeanFactory的构造函数中.

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
    private final Set<Class<?>> ignoredDependencyInterfaces = new HashSet<>();

    public AbstractAutowireCapableBeanFactory() {
        super();
        ignoreDependencyInterface(BeanNameAware.class);
        ignoreDependencyInterface(BeanFactoryAware.class);
        ignoreDependencyInterface(BeanClassLoaderAware.class);
    }

    public void ignoreDependencyInterface(Class<?> ifc) {
        this.ignoredDependencyInterfaces.add(ifc);
    }
}

这里需要关注的是ignoreDependencyInterface方法, 其主要功能是忽略给定接口的自动装配.

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
    // 关于Spring中Resource接口及其相关实现类查看google说明.
    public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
        // 使用一个ThreadLocal来存放配置文件.
        Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
        if (currentResources == null) {
            currentResources = new HashSet<>(4);
            this.resourcesCurrentlyBeingLoaded.set(currentResources);
        }
        if (!currentResources.add(encodedResource)) {
            throw new BeanDefinitionStoreException("");
        }
        try {
            // 从EncodedResource中获取输入流, 根据流创建org.xml.sax.InputSource类
            InputStream inputStream = encodedResource.getResource().getInputStream();
            try {
                InputSource inputSource = new InputSource(inputStream);
                if (encodedResource.getEncoding() != null) {
                    inputSource.setEncoding(encodedResource.getEncoding());
                }
                // 该方法是逻辑的核心部分.
                return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
            } finally {
                inputStream.close();
            }
        } catch (IOException ex) {
            throw new BeanDefinitionStoreException("IOException parsing XML document from " + encodedResource.getResource(), ex);
        } finally {
            currentResources.remove(encodedResource);
            if (currentResources.isEmpty()) {
                this.resourcesCurrentlyBeingLoaded.remove();
            }
        }
    }

    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
        try {
            Document doc = doLoadDocument(inputSource, resource); // 加载XML文件, 并得到对应的Document.
            return registerBeanDefinitions(doc, resource); // 根据返回的Document注册Bean信息.
        } catch (Exception ex) {
            throw ex;
        } 
    }
    protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
        return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
                                                getValidationModeForResource(resource), // 获取对XML文件的验证模式
                                                isNamespaceAware());
    }
}

上述代码只是Spring加载解析配置文件的开始, 在分析registerBeanDefinitions方法之前, 先从获取XML文件的验证模式说起.

2.1.1 XML验证模式

了解XML文件的都应该知道, XML文件的验证模式保证了XML文件的正确性, 而XML的验证模式大致可以分为DTD和XSD. DTD在现在基本被淘汰, 可以直接忽略, 此处直接介绍XSD.

XSD描述了XML文档的结构, 可以用一个指定的XML Schema来验证某个XML文档, 以检查XML文档是否符合其要求. 在验证时, 除了要声明空间外(xmlns="http://www.springframework.org/schema/beans"), 还必须指定该名称空间对应的XML Schema文档的存储位置(xsi:schemaLocation="..."). 它包含两部分, 一部分是名称空间的uri, 另一部分就是该名称空间所标识的XML Schema文件位置或URL地址.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
    protected int getValidationModeForResource(Resource resource) {
        int validationModeToUse = getValidationMode();
        // 如果手动指定了验证模式, 则使用指定的验证模式.
        if (validationModeToUse != VALIDATION_AUTO) {
            return validationModeToUse;
        }
        // 自动检测
        int detectedMode = detectValidationMode(resource);
        if (detectedMode != VALIDATION_AUTO) {
            return detectedMode;
        }
        return VALIDATION_XSD;
    }
    protected int detectValidationMode(Resource resource) {
        if (resource.isOpen()) {
            throw new BeanDefinitionStoreException();
        }

        InputStream inputStream;
        try {
            inputStream = resource.getInputStream();
        } catch (IOException ex) {
            throw new BeanDefinitionStoreException("..", ex);
        }

        try {
            return this.validationModeDetector.detectValidationMode(inputStream);
        } catch (IOException ex) {
            throw new BeanDefinitionStoreException("..", ex);
        }
    }
}

public class XmlValidationModeDetector {
    public int detectValidationMode(InputStream inputStream) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        try {
            boolean isDtdValidated = false;
            String content;
            while ((content = reader.readLine()) != null) {
                content = consumeCommentTokens(content);
                // 如果读取的行是空或者是注释则略过.
                if (this.inComment || !StringUtils.hasText(content)) {
                    continue;
                }
                // 是否包含DOCTYPE, 如果包含的话就是DTD模式
                if (hasDoctype(content)) {
                    isDtdValidated = true;
                    break;
                }
                // 读取到<开始符号, 验证模式一定会在开始符号之前.
                if (hasOpeningTag(content)) {
                    // End of meaningful data...
                    break;
                }
            }
            return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD);
        } catch (CharConversionException ex) {
            return VALIDATION_AUTO;
        } finally {
            reader.close();
        }
    }
}

2.1.2 获取Document

XML验证完成之后, 即可以进行Document加载了.

public class DefaultDocumentLoader implements DocumentLoader {
    @Override
    public Document loadDocument(InputSource inputSource, EntityResolver entityResolver, 
                                ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
        DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
        DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
        return builder.parse(inputSource);
    }

    protected DocumentBuilderFactory createDocumentBuilderFactory(int validationMode, boolean namespaceAware) throws ParserConfigurationException {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(namespaceAware);

        if (validationMode != XmlValidationModeDetector.VALIDATION_NONE) {
            factory.setValidating(true);
            if (validationMode == XmlValidationModeDetector.VALIDATION_XSD) {
                factory.setNamespaceAware(true);
                try {
                    factory.setAttribute(SCHEMA_LANGUAGE_ATTRIBUTE, XSD_SCHEMA_LANGUAGE);
                } catch (IllegalArgumentException ex) {
                    ParserConfigurationException pcex = new ParserConfigurationException("");
                    pcex.initCause(ex);
                    throw pcex;
                }
            }
        }
        return factory;
    }
    protected DocumentBuilder createDocumentBuilder(DocumentBuilderFactory factory, EntityResolver entityResolver, ErrorHandler errorHandler) throws ParserConfigurationException {
        DocumentBuilder docBuilder = factory.newDocumentBuilder();
        if (entityResolver != null) {
            docBuilder.setEntityResolver(entityResolver);
        }
        if (errorHandler != null) {
            docBuilder.setErrorHandler(errorHandler);
        }
        return docBuilder;
    }
}

对于这部分代码并没有太多可以描述的, 因为SAX解析XML的代码基本都是类似的. 先创建DocumentBuilderFactory, 再通过DocumentBuilderFactory创建DocumentBuilder, 进而解析inputSource来返回Document对象. 此处需要注意的是, 在createDocumentBuilder方法参数中, 传入通过getEntityResolver方法获取的返回值.

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
    protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
        return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
                getValidationModeForResource(resource), isNamespaceAware());
    }

    protected EntityResolver getEntityResolver() {
        if (this.entityResolver == null) {
            // Determine default EntityResolver to use.
            ResourceLoader resourceLoader = getResourceLoader();
            if (resourceLoader != null) {
                this.entityResolver = new ResourceEntityResolver(resourceLoader);
            } else {
                this.entityResolver = new DelegatingEntityResolver(getBeanClassLoader());
            }
        }
        return this.entityResolver;
    }
}

2.1.3 EntityResolver用法

如果SAX解析XML时, 需要实现自定义处理外部实体, 则必须实现此接口并使用setEntityResolver方法向SAX驱动器注册一个实例, 这就是EntityResolver的主要用途. 也就是说, 解析一个XML, SAX首先读取XML文档上的声明, 根据声明去寻找相应的DTD定义. 默认的寻找规则就是通过网络下载相应的DTD声明并进行验证. EntityResolver的作用是项目本身就可以提供一个如何寻找DTD声明的方法, 比如我们将DTD文件直接存放在项目的某处, 在实现时直接将此文档读取并返回给SAX即可.

2.2 解析Document

在文件转换为Document之后, 接下来就是如何解析Document了, 回到XmlBeanDefinitionReader中的doLoadBeanDefinitions方法中, 查看registerBeanDefinitions方法的具体实现.

public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader, EnvironmentCapable {
    private final BeanDefinitionRegistry registry;
    
    protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
        this.registry = registry;
    }
    
    @Override
    public final BeanDefinitionRegistry getRegistry() {
        return this.registry;
    }
}
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
    private Class<? extends BeanDefinitionDocumentReader> documentReaderClass = DefaultBeanDefinitionDocumentReader.class;
    public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
        // 需要注意此处的registry参数. 默认使用BeanDefinitionRegistry的子类DefaultListableBeanFactory
        super(registry); 
    }
    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
        try {
            Document doc = doLoadDocument(inputSource, resource);
            return registerBeanDefinitions(doc, resource); // 进入该方法.
        } catch (Exception ex) {
            throw ex;
        }
    }
    public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
        // 此处实例化BeanDefinitionDocumentReader的子类DefaultBeanDefinitionDocumentReader.
        BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
        // 记录统计前BeanDefinition的加载个数
        int countBefore = getRegistry().getBeanDefinitionCount(); 
        // 加载及注册Bean
        documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
        // 返回本次加载的BeanDefinition个数
        return getRegistry().getBeanDefinitionCount() - countBefore;
    }
    protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
        return BeanUtils.instantiateClass(this.documentReaderClass);
    }
}

此处将解析Document的任务委托给了BeanDefinitionDocumentReader的子类DefaultBeanDefinitionDocumentReader. 进入DefaultBeanDefinitionDocumentReader类, 可以看到核心方法: doRegisterBeanDefinitions方法. 如果前面一直是XML加载解析的准备阶段, 那么doRegisterBeanDefinitions算是真正地开始进行解析了.

public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
    private XmlReaderContext readerContext;
    private BeanDefinitionParserDelegate delegate;
    
    @Override
    public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
        this.readerContext = readerContext;
        doRegisterBeanDefinitions(doc.getDocumentElement());
    }
    
    protected void doRegisterBeanDefinitions(Element root) {
        // 处理解析的具体类, 此处的BeanDefinitionParserDelegate是一个比较重要的类, 负责解析Bean的定义.
        BeanDefinitionParserDelegate parent = this.delegate;
        this.delegate = createDelegate(getReaderContext(), root, parent);
        
        if (this.delegate.isDefaultNamespace(root)) {
            // 获取<beans profile='xxx'>中的profile, 判断是否是当前环境.
            // 如果当前激活的profile不是此处获取的profile, 那么不会对<beans>进行解析
            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)) {
                    return;
                }
            }
        }
        preProcessXml(root); // 解析前处理, 留给子类实现.
        parseBeanDefinitions(root, this.delegate);
        postProcessXml(root); // 解析后处理, 留给子类实现.

        this.delegate = parent;
    }
    
    protected BeanDefinitionParserDelegate createDelegate(XmlReaderContext readerContext, Element root, @Nullable BeanDefinitionParserDelegate parentDelegate) {
        BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
        delegate.initDefaults(root, parentDelegate);
        return delegate;
    }
    
    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        // 使用node.getNamespaceURI()获取命名空间, 之后与Spring中固定的命名空间(http://www.springframework.org/schema/beans)进行对比以此判断是否是默认命名空间
        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解析的节点是import、alias、bean、beans这四个. 之所以是这四个, 是因为他们处于http://www.springframework.org/schema/beans这个namespace中. 在使用其他标签(mvc、task、context等)时, xml中需要引入相应的namespace和xsd文件, 同时代码中需要提供相应的parser来解析, 如MvcNamespaceHandler、TaskNamespaceHandler、ContextNamespaceHandler等.

2.3 解析默认标签

默认标签的解析是在parseDefaultElement中进行的, 分别对4中不同标签(import、alias、bean、beans)做了不同的处理.

public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { // import
            importBeanDefinitionResource(ele);
        } else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { // alias
            processAliasRegistration(ele);
        } else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { // bean
            processBeanDefinition(ele, delegate);
        } else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // beans
            doRegisterBeanDefinitions(ele);
        }
    }
}

2.3.1 解析bean标签

public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        // 委托BeanDefinitionParserDelegate的parseBeanDefinitionElement方法进行元素解析,
        // 返回的bdHolder中已经包含了配置文件中的各种属性了, 比如class、name、id等等.
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
            // 如果默认标签的子节点存在自定义的属性, 则再次对自定义标签进行解析.
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
            try {
                // 解析完成后进行注册. 该操作委托给了BeanDefinitionReaderUtils. 
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
            } catch (BeanDefinitionStoreException ex) {
                getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex);
            }
            // 发出响应事件, 通知相关的监听器. 
            getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }
    }
}

在继续分析之前, 我们先看下 <bean /> 标签中可以定义哪些属性(部分重要属性):

名称 说明
class 类的全限定名
name 可指定 id、name(用逗号、分号、空格分隔)
scope 作用域
constructor arguments 指定构造参数
properties 设置属性的值
autowiring mode no(默认值)、byName、byType、 constructor
lazy-initialization mode 是否懒加载(如果被非懒加载的bean依赖了那么其实也就不能懒加载了)
initialization method bean 属性设置完成后, 会调用这个方法
destruction method bean 销毁后的回调方法

一个简单bean配置就像下面这样

<bean id="exampleBean" name="name1, name2, name3" class="com.javadoop.ExampleBean"
      scope="singleton" lazy-init="true" init-method="init" destroy-method="cleanup">
    <constructor-arg type="int" value="7500000"/>
    <property name="beanTwo" ref="yetAnotherBean"/>
</bean>

继续分析代码, 接下来进入BeanDefinitionParserDelegate的parseBeanDefinitionElement方法中.

public class BeanDefinitionParserDelegate {
    public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
        return parseBeanDefinitionElement(ele, null);
    }
    public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
        String id = ele.getAttribute(ID_ATTRIBUTE);
        String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

        List<String> aliases = new ArrayList<>();
        // 切分name属性并添加到alias集合中
        if (StringUtils.hasLength(nameAttr)) { 
            String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
            aliases.addAll(Arrays.asList(nameArr));
        }

        String beanName = id; // 生成beanName, 如果没有ID属性的话, 那么就使用alias中的第一个.
        if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
            beanName = aliases.remove(0);
        }

        if (containingBean == null) {
            checkNameUniqueness(beanName, aliases, ele);
        }
        // 根据bean标签中的配置创建BeanDefinition, 运行本行代码之后, 整个bean标签就算是解析完成了.
        AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
        if (beanDefinition != null) {
            // 如果没有设置id或者name(beanName还是为空)的话, 此时就会根据Spring中提供的命名规则为当前bean生成beanName.
            if (!StringUtils.hasText(beanName)) {
                try {
                    if (containingBean != null) {
                        beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);
                    } else {
                        beanName = this.readerContext.generateBeanName(beanDefinition);
                        String beanClassName = beanDefinition.getBeanClassName();
                        if (beanClassName != null &&
                                beanName.startsWith(beanClassName) && 
                                beanName.length() > beanClassName.length() &&
                                !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
                            aliases.add(beanClassName);
                        }
                    }
                } catch (Exception ex) {
                    error(ex.getMessage(), ele);
                    return null;
                }
            }
            String[] aliasesArray = StringUtils.toStringArray(aliases);
            return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
        }

        return null;
    }
    
    public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, @Nullable BeanDefinition containingBean) {
        this.parseState.push(new BeanEntry(beanName));
        // 解析class属性
        String className = null;
        if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
            className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
        }
        // 解析parent属性
        String parent = null;
        if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
            parent = ele.getAttribute(PARENT_ATTRIBUTE);
        }

        try {
            // 创建BeanDefinition的子类GenericBeanDefinition
            AbstractBeanDefinition bd = createBeanDefinition(className, parent); // 1. 创建BeanDefinition
            // 设置BeanDefinition的一些属性, 这些属性都定义在AbstractBeanDefinition中.
            parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); // 2. 解析各种属性
            bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

            // 解析bean标签中的子标签
            parseMetaElements(ele, bd); // 3. 解析子元素meta
            parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); // 4. 解析子元素lookup-method
            parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); // 5. 解析子元素replace-method

            parseConstructorArgElements(ele, bd); // 6. 解析子元素constructor-arg
            parsePropertyElements(ele, bd); // 7. 解析子元素property
            parseQualifierElements(ele, bd); // 8. 解析子元素qualifier

            bd.setResource(this.readerContext.getResource());
            bd.setSource(extractSource(ele));

            return bd;
        } catch (Exception ex) {
            // ...
        } finally {
            this.parseState.pop();
        }

        return null;
    }
}

上述代码就是对默认标签解析的全过程了. 主要可以分为以下几个步骤.

1. 创建BeanDefinition

BeanDefinition是一个接口, 表示配置文件中bean标签在容器中的内部表现形式, 在Spring中存在三种实现: RootBeanDefinition、ChildBeanDefinition、GenericBeanDefinition, 三种实现均继承自AbstractBeanDefinition. 在配置文件中可以定义父bean和子bean, 父bean使用RootBeanDefinition表示, 而子bean用ChildBeanDefinition表示, 而没有父bean的bean就使用RootBeanDefinition表示.

由此可见, 要解析属性首先要创建用于承载属性的实例: GenericBeanDefinition. 而代码createBeanDefinition(className, parent)的作用就是实现此功能.

public class BeanDefinitionParserDelegate {
    protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, 
        @Nullable String parentName) throws ClassNotFoundException {

        return BeanDefinitionReaderUtils.createBeanDefinition(parentName, className, this.readerContext.getBeanClassLoader());
    }
}
public abstract class BeanDefinitionReaderUtils {
    public static AbstractBeanDefinition createBeanDefinition(@Nullable String parentName, 
        @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {

        GenericBeanDefinition bd = new GenericBeanDefinition();
        bd.setParentName(parentName);
        if (className != null) {
            if (classLoader != null) {
                bd.setBeanClass(ClassUtils.forName(className, classLoader));
            } else {
                bd.setBeanClassName(className);
            }
        }
        return bd;
    }
}
2. 解析各种属性

创建完BeanDefinition实例后, 便可以对bean信息的各种属性进行解析了, 首先进入parseBeanDefinitionAttributes方法, 该方法是对element所有元素属性进行解析.

public class BeanDefinitionParserDelegate {
    // 设置BeanDefinition的一些属性, 这些属性都定义在AbstractBeanDefinition中.
    public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
            @Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {

        // scope
        if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) { // singleton不再被支持, 替换为scope
            error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
        } else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
            bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
        } else if (containingBean != null) {
            // 在嵌入BeanDefinition情况下并且没有单独制定scope属性, 默认使用父类的属性.
            bd.setScope(containingBean.getScope());
        }
        // abstract
        if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
            bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
        }
        // lazy-init
        String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
        if (isDefaultValue(lazyInit)) {
            lazyInit = this.defaults.getLazyInit();
        }
        bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
        // autowire
        String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
        bd.setAutowireMode(getAutowireMode(autowire));
        // depends-on
        if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
            String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
            bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
        }
        // autowire-candidate
        String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
        if (isDefaultValue(autowireCandidate)) {
            String candidatePattern = this.defaults.getAutowireCandidates();
            if (candidatePattern != null) {
                String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
                bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
            }
        } else {
            bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
        }
        // primary
        if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
            bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
        }
        // init-method
        if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
            String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
            bd.setInitMethodName(initMethodName);
        } else if (this.defaults.getInitMethod() != null) {
            bd.setInitMethodName(this.defaults.getInitMethod());
            bd.setEnforceInitMethod(false);
        }
        // destroy-method
        if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
            String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
            bd.setDestroyMethodName(destroyMethodName);
        } else if (this.defaults.getDestroyMethod() != null) {
            bd.setDestroyMethodName(this.defaults.getDestroyMethod());
            bd.setEnforceDestroyMethod(false);
        }
        // factory-method
        if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
            bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
        }
        // factory-bean
        if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
            bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
        }

        return bd;
    }
}

上述代码中可以清晰的看到Spring完成了对所有属性的解析, 这些属性有些事我们经常使用到的, 不了解的可以查阅相关资料.

3. 解析子元素meta

在开始解析meta之前, 先看下如何使用meta属性.

<bean id="bean1" class="com.Bean1">
    <meta key="metaName" value="metaValue" />
</bean>

这段代码不会体现在bean1的属性中, 而是一个额外的声明, 当需要时可以通过BeanDefinition的getAttribute(key)方法进行获取.

public class BeanDefinitionParserDelegate {

    public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) {
        NodeList nl = ele.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            // 提取meta数据
            if (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) {
                Element metaElement = (Element) node;
                String key = metaElement.getAttribute(KEY_ATTRIBUTE); // key
                String value = metaElement.getAttribute(VALUE_ATTRIBUTE); // value
                BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);
                attribute.setSource(extractSource(metaElement));
                attributeAccessor.addMetadataAttribute(attribute);
            }
        }
    }
}
4. 解析子元素lookup-method

子元素lookup-method可以用在设计有些可插拔的功能上.

public class ClassA {
    public String method() {
        System.out.println("classA");
    }
}

public abstract class ClassB {
    public void print() {
        this.getClassA().method();
    }
    
    public abstract ClassA getClassA();
}
<bean id="classA" class="com.classA" />
<bean id="classB" class="com.ClassB">
    <lookup-method name="getClassA" bean="classA" />
</bean>

在ClassB中, 并没有实现抽象方法getClassA(), 而在配置文件中, 动态的将classA这个bean作为getClassA的返回值.

public class BeanDefinitionParserDelegate {

    public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) {
        NodeList nl = beanEle.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            // 解析lookup-method标签
            if (isCandidateElement(node) && nodeNameEquals(node, LOOKUP_METHOD_ELEMENT)) {
                Element ele = (Element) node;
                String methodName = ele.getAttribute(NAME_ATTRIBUTE); 
                String beanRef = ele.getAttribute(BEAN_ELEMENT);
                LookupOverride override = new LookupOverride(methodName, beanRef);
                override.setSource(extractSource(ele));
                overrides.addOverride(override);
            }
        }
    }
}

上述代码与parseMetaElements类似, 最大的区别是在if判断中被修改为LOOKUP_METHOD_ELEMENT.

5. 解析子元素replace-method

该标签可以在运行时用新的方法替换现有的方法.

public class ClassA {
    public void method() {
        System.out.println("classA");
    }
}

public class ClassB implements MethodReplacer {
    @override
    public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
        System.out.println("classB");
    }
}
<bean id="classA" class="com.classA" />
<bean id="classB" class="com.ClassB">
    <replace-method name="method" replacer="classA" />
</bean>

以上就是标签replace-method的使用方式, 接下来分析下Spring是如何解析replace-method的.

public class BeanDefinitionParserDelegate {

    public void parseReplacedMethodSubElements(Element beanEle, MethodOverrides overrides) {
        NodeList nl = beanEle.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            // 解析replace-method
            if (isCandidateElement(node) && nodeNameEquals(node, REPLACED_METHOD_ELEMENT)) {
                Element replacedMethodEle = (Element) node;
                // 提取需要替换的旧方法
                String name = replacedMethodEle.getAttribute(NAME_ATTRIBUTE);
                // 提取对应的新方法
                String callback = replacedMethodEle.getAttribute(REPLACER_ATTRIBUTE);
                ReplaceOverride replaceOverride = new ReplaceOverride(name, callback);
                // Look for arg-type match elements.
                List<Element> argTypeEles = DomUtils.getChildElementsByTagName(replacedMethodEle, ARG_TYPE_ELEMENT);
                for (Element argTypeEle : argTypeEles) {
                    // 记录参数
                    String match = argTypeEle.getAttribute(ARG_TYPE_MATCH_ATTRIBUTE);
                    match = (StringUtils.hasText(match) ? match : DomUtils.getTextValue(argTypeEle));
                    if (StringUtils.hasText(match)) {
                        replaceOverride.addTypeIdentifier(match);
                    }
                }
                replaceOverride.setSource(extractSource(replacedMethodEle));
                overrides.addOverride(replaceOverride);
            }
        }
    }
}
6. 解析子元素constructor-arg

接下来就是解析构造函数标签(constructor-arg)了.

public class BeanDefinitionParserDelegate {
    public void parseConstructorArgElements(Element beanEle, BeanDefinition bd) {
        NodeList nl = beanEle.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (isCandidateElement(node) && nodeNameEquals(node, CONSTRUCTOR_ARG_ELEMENT)) {
                // 解析constructor-arg标签
                parseConstructorArgElement((Element) node, bd);
            }
        }
    }
    
    public void parseConstructorArgElement(Element ele, BeanDefinition bd) {
        // 获取index属性
        String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE);
        // 获取type属性
        String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE);
        // 获取name属性
        String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
        if (StringUtils.hasLength(indexAttr)) {
            try {
                int index = Integer.parseInt(indexAttr);
                if (index < 0) {
                    error("'index' cannot be lower than 0", ele);
                } else {
                    try {
                        this.parseState.push(new ConstructorArgumentEntry(index));
                        // 解析constructor-arg上的属性和子元素
                        Object value = parsePropertyValue(ele, bd, null);
                        // 封装解析出来的元素
                        ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
                        if (StringUtils.hasLength(typeAttr)) {
                            valueHolder.setType(typeAttr);
                        }
                        if (StringUtils.hasLength(nameAttr)) {
                            valueHolder.setName(nameAttr);
                        }
                        valueHolder.setSource(extractSource(ele));
                        // 不允许重复指定相同的参数
                        if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) {
                            error("Ambiguous constructor-arg entries for index " + index, ele);
                        } else {
                            bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder);
                        }
                    } finally {
                        this.parseState.pop();
                    }
                }
            } catch (NumberFormatException ex) {
                error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele);
            }
        } else {
            try {
                this.parseState.push(new ConstructorArgumentEntry());
                Object value = parsePropertyValue(ele, bd, null);
                ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
                if (StringUtils.hasLength(typeAttr)) {
                    valueHolder.setType(typeAttr);
                }
                if (StringUtils.hasLength(nameAttr)) {
                    valueHolder.setName(nameAttr);
                }
                valueHolder.setSource(extractSource(ele));
                bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder);
            } finally {
                this.parseState.pop();
            }
        }
    }
    // 解析constructor-arg上的属性和子元素
    public Object parsePropertyValue(Element ele, BeanDefinition bd, @Nullable String propertyName) {
        String elementName = (propertyName != null ?
                "<property> element for property '" + propertyName + "'" :
                "<constructor-arg> element");
        // 一个属性对应一种类型: ref、value、list等等
        NodeList nl = ele.getChildNodes();
        Element subElement = null;
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            // 对应description或者meta不做处理
            if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) && !nodeNameEquals(node, META_ELEMENT)) {
                // Child element is what we're looking for.
                if (subElement != null) {
                    error(elementName + " must not contain more than one sub-element", ele);
                } else {
                    subElement = (Element) node;
                }
            }
        }
        // 判断constructor-arg上是否有ref属性
        boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
        // 判断constructor-arg上是否有value属性
        boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
        if ((hasRefAttribute && hasValueAttribute) || // 同时有ref属性和value属性
            ((hasRefAttribute || hasValueAttribute) && subElement != null)) { // 存在ref或者value, 并且有子元素
            error(elementName + " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
        }
        if (hasRefAttribute) {
            // ref属性处理
            String refName = ele.getAttribute(REF_ATTRIBUTE);
            if (!StringUtils.hasText(refName)) {
                error(elementName + " contains empty 'ref' attribute", ele);
            }
            RuntimeBeanReference ref = new RuntimeBeanReference(refName);
            ref.setSource(extractSource(ele));
            return ref;
        } else if (hasValueAttribute) {
            // value属性处理
            TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
            valueHolder.setSource(extractSource(ele));
            return valueHolder;
        } else if (subElement != null) {
            // 子元素处理
            return parsePropertySubElement(subElement, bd);
        } else {
            // Neither child element nor "ref" or "value" attribute found.
            error(elementName + " must specify a ref or value", ele);
            return null;
        }
    }
    
    // 解析constructor-arg下的子元素
    public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd, @Nullable String defaultValueType) {
        if (!isDefaultNamespace(ele)) {
            // 自定义标签解析, 后续会讲
            return parseNestedCustomElement(ele, bd);
        } else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
            // bean标签解析
            BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);
            if (nestedBd != null) {
                // 自定义标签解析
                nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
            }
            return nestedBd;
        } else if (nodeNameEquals(ele, REF_ELEMENT)) {
            // ref标签
            String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);
            boolean toParent = false;
            if (!StringUtils.hasLength(refName)) {
                refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);
                toParent = true;
                if (!StringUtils.hasLength(refName)) {
                    error("'bean' or 'parent' is required for <ref> element", ele);
                    return null;
                }
            }
            if (!StringUtils.hasText(refName)) {
                error("<ref> element contains empty target attribute", ele);
                return null;
            }
            RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);
            ref.setSource(extractSource(ele));
            return ref;
        } else if (nodeNameEquals(ele, IDREF_ELEMENT)) {
            // idref标签
            return parseIdRefElement(ele);
        } else if (nodeNameEquals(ele, VALUE_ELEMENT)) {
            // value标签
            return parseValueElement(ele, defaultValueType);
        } else if (nodeNameEquals(ele, NULL_ELEMENT)) {
            // null标签
            TypedStringValue nullHolder = new TypedStringValue(null);
            nullHolder.setSource(extractSource(ele));
            return nullHolder;
        } else if (nodeNameEquals(ele, ARRAY_ELEMENT)) {
            // array标签
            return parseArrayElement(ele, bd);
        } else if (nodeNameEquals(ele, LIST_ELEMENT)) {
            // list标签
            return parseListElement(ele, bd);
        } else if (nodeNameEquals(ele, SET_ELEMENT)) {
            // set标签
            return parseSetElement(ele, bd);
        } else if (nodeNameEquals(ele, MAP_ELEMENT)) {
            // map标签
            return parseMapElement(ele, bd);
        } else if (nodeNameEquals(ele, PROPS_ELEMENT)) {
            // props标签
            return parsePropsElement(ele);
        } else {
            error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
            return null;
        }
    }
}

上述代码的逻辑比较清晰, 依次解析constructor-arg中的属性以及其子标签.

7. 解析子元素property

解析子元素property, 没啥好说的, 直接看代码.

public class BeanDefinitionParserDelegate {
    public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
        NodeList nl = beanEle.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
                // 解析子元素property
                parsePropertyElement((Element) node, bd);
            }
        }
    }
    public void parsePropertyElement(Element ele, BeanDefinition bd) {
        // 解析property上的name属性
        String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
        if (!StringUtils.hasLength(propertyName)) {
            error("Tag 'property' must have a 'name' attribute", ele);
            return;
        }
        this.parseState.push(new PropertyEntry(propertyName));
        try {
            // 不允许多次对同一个属性进行配置
            if (bd.getPropertyValues().contains(propertyName)) {
                error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
                return;
            }
            // parsePropertyValue方法参照constructor-arg标签时的代码说明
            Object val = parsePropertyValue(ele, bd, propertyName);
            PropertyValue pv = new PropertyValue(propertyName, val);
            parseMetaElements(ele, pv); // 参照meta标签的说明
            pv.setSource(extractSource(ele));
            bd.getPropertyValues().addPropertyValue(pv);
        } finally {
            this.parseState.pop();
        }
    }
}
8. 解析子元素qualifier

这个标签指定自动注入时bean的名称, 可以查看注解@Qualifier.

public class BeanDefinitionParserDelegate {
    public void parseQualifierElements(Element beanEle, AbstractBeanDefinition bd) {
        NodeList nl = beanEle.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ELEMENT)) {
                parseQualifierElement((Element) node, bd);
            }
        }
    }
    
    public void parseQualifierElement(Element ele, AbstractBeanDefinition bd) {
        // qualifier标签属性type
        String typeName = ele.getAttribute(TYPE_ATTRIBUTE);
        if (!StringUtils.hasLength(typeName)) {
            error("Tag 'qualifier' must have a 'type' attribute", ele);
            return;
        }
        this.parseState.push(new QualifierEntry(typeName));
        try {
            AutowireCandidateQualifier qualifier = new AutowireCandidateQualifier(typeName);
            qualifier.setSource(extractSource(ele));
            // qualifier标签属性value
            String value = ele.getAttribute(VALUE_ATTRIBUTE);
            if (StringUtils.hasLength(value)) {
                qualifier.setAttribute(AutowireCandidateQualifier.VALUE_KEY, value);
            }
            NodeList nl = ele.getChildNodes();
            for (int i = 0; i < nl.getLength(); i++) {
                Node node = nl.item(i);
                if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ATTRIBUTE_ELEMENT)) {
                    // 解析qualifier下的子标签attribute
                    Element attributeEle = (Element) node;
                    String attributeName = attributeEle.getAttribute(KEY_ATTRIBUTE);
                    String attributeValue = attributeEle.getAttribute(VALUE_ATTRIBUTE);
                    if (StringUtils.hasLength(attributeName) && StringUtils.hasLength(attributeValue)) {
                        BeanMetadataAttribute attribute = new BeanMetadataAttribute(attributeName, attributeValue);
                        attribute.setSource(extractSource(attributeEle));
                        qualifier.addMetadataAttribute(attribute);
                    } else {
                        error("Qualifier 'attribute' tag must have a 'name' and 'value'", attributeEle);
                        return;
                    }
                }
            }
            bd.addQualifier(qualifier);
        } finally {
            this.parseState.pop();
        }
    }
}
9. bean标签下的自定义属性

回到DefaultBeanDefinitionDocumentReader的processBeanDefinition方法中, 分析完delegate.parseBeanDefinitionElement(ele)之后开始详细分析delegate.decorateBeanDefinitionIfRequired(ele, bdHolder).

<bean id="classA" class="com.ClassA">
    <myBean:user name="name" />
</bean>

在Spring的配置中, 如果bean标签下使用了自定义标签时, delegate.decorateBeanDefinitionIfRequired(ele, bdHolder)便会起作用了.

public class BeanDefinitionParserDelegate {
    public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) {
        // 第三个参数是父类Bean, 当对某个嵌套配置进行分析时(查看BeanDefinitionParserDelegate中parsePropertySubElement方法内解析bean标签代码),
        // 这里需要传递父BeanDefinition. 分析代码可知, 其实是为了使用父类的scope属性
        return decorateBeanDefinitionIfRequired(ele, definitionHolder, null);
    }

    public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder, @Nullable BeanDefinition containingBd) {
        BeanDefinitionHolder finalDefinition = definitionHolder;
        NamedNodeMap attributes = ele.getAttributes();
        // 遍历所有属性, 查看是否有适用于修饰的属性.
        for (int i = 0; i < attributes.getLength(); i++) {
            Node node = attributes.item(i);
            finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
        }
        // 遍历所有的子节点, 查看是否有适用于修饰的属性.
        NodeList children = ele.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            Node node = children.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
            }
        }
        return finalDefinition;
    }
    
    public BeanDefinitionHolder decorateIfRequired(Node node, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {
        // 获取自定义标签的命名空间
        String namespaceUri = getNamespaceURI(node);
        if (namespaceUri != null && !isDefaultNamespace(namespaceUri)) {
            // 根据命名空间找到对应的处理器
            NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
            if (handler != null) {
                // 此处进行修饰, 这部分会在解析自定义标签时详细说明.
                BeanDefinitionHolder decorated = handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
                if (decorated != null) {
                    return decorated;
                }
            } else if (namespaceUri.startsWith("http://www.springframework.org/")) {
                error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node);
            } else {
                if (logger.isDebugEnabled()) {
                    logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]");
                }
            }
        }
        return originalDef;
    }
}
10. 注册Bean

当bean标签解析完成后, 回到DefaultBeanDefinitionDocumentReader中processBeanDefinition方法内, 可以看到接下来调用了BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())开始注册bean. 简单来说就是将BeanDefinition存放到两个map中, 分别对应beanName和alias.

public abstract class BeanDefinitionReaderUtils {
    
    public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
        // 根据beanName注册
        String beanName = definitionHolder.getBeanName();
        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

        // 根据alias注册
        String[] aliases = definitionHolder.getAliases();
        if (aliases != null) {
            for (String alias : aliases) {
                registry.registerAlias(beanName, alias);
            }
        }
    }
}
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
        implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
        
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
    
    private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
    
    private volatile Set<String> manualSingletonNames = new LinkedHashSet<>(16);
    
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
        Assert.hasText(beanName, "Bean name must not be empty");
        Assert.notNull(beanDefinition, "BeanDefinition must not be null");

        if (beanDefinition instanceof AbstractBeanDefinition) {
            try {
                // 进行最后一次校验, 主要对于AbstractBeanDefinition属性中的methodOverrides校验, 
                // 校验methodOverrides是否与工厂方法并存或者methodOverrides对应的方法不存在
                ((AbstractBeanDefinition) beanDefinition).validate();
            } catch (BeanDefinitionValidationException ex) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                        "Validation of bean definition failed", ex);
            }
        }
        BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
        if (existingDefinition != null) {
            // 已经注册的beanName, 并且配置中配置了不允许覆盖, 抛出异常.
            if (!isAllowBeanDefinitionOverriding()) {
                throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
            } else if (existingDefinition.getRole() < beanDefinition.getRole()) {
                logger.info("...");
            } else if (!beanDefinition.equals(existingDefinition)) {
                logger.info("...");
            } else {
                logger.info("...");
            }
            // 直接覆盖
            this.beanDefinitionMap.put(beanName, beanDefinition);
        } else {
            if (hasBeanCreationStarted()) { // 是否到启动阶段
                // Cannot modify startup-time collection elements anymore (for stable iteration)
                synchronized (this.beanDefinitionMap) {
                    // 注册到Map中
                    this.beanDefinitionMap.put(beanName, beanDefinition);
                    // 使用新的beanDefinitionNames替换旧的
                    List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                    updatedDefinitions.addAll(this.beanDefinitionNames);
                    updatedDefinitions.add(beanName);
                    this.beanDefinitionNames = updatedDefinitions;
                    // 从集合中移除beanName
                    removeManualSingletonName(beanName);
                }
            } else {
                this.beanDefinitionMap.put(beanName, beanDefinition);
                this.beanDefinitionNames.add(beanName);
                removeManualSingletonName(beanName);
            }
            this.frozenBeanDefinitionNames = null;
        }

        if (existingDefinition != null || containsSingleton(beanName)) {
            // 重置所有beanName对应的缓存
            resetBeanDefinition(beanName);
        }
    }
    
    private void removeManualSingletonName(String beanName) {
        updateManualSingletonNames(set -> set.remove(beanName), set -> set.contains(beanName));
    }
    
    private void updateManualSingletonNames(Consumer<Set<String>> action, Predicate<Set<String>> condition) {
        if (hasBeanCreationStarted()) {
            // Cannot modify startup-time collection elements anymore (for stable iteration)
            synchronized (this.beanDefinitionMap) {
                // manualSingletonNames中存在beanName, 则删除
                if (condition.test(this.manualSingletonNames)) { // 存在
                    Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
                    action.accept(updatedSingletons);
                    this.manualSingletonNames = updatedSingletons;
                }
            }
        } else {
            // manualSingletonNames中存在beanName, 则删除
            if (condition.test(this.manualSingletonNames)) {
                action.accept(this.manualSingletonNames);
            }
        }
    }
}
public class SimpleAliasRegistry implements AliasRegistry {

    private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);
    
    public void registerAlias(String name, String alias) {
        Assert.hasText(name, "'name' must not be empty");
        Assert.hasText(alias, "'alias' must not be empty");
        synchronized (this.aliasMap) {
            // beanName与alias相同, 不记录alias, 并且删除对应的alias
            if (alias.equals(name)) {
                this.aliasMap.remove(alias);
            } else {
                String registeredName = this.aliasMap.get(alias);
                if (registeredName != null) {
                    if (registeredName.equals(name)) {
                        return;
                    }
                    // 不允许覆盖, 抛出异常
                    if (!allowAliasOverriding()) 
                        throw new IllegalStateException("...");
                }
                // 如果A->B存在, 再次出现A->C时会抛出异常
                checkForAliasCircle(name, alias);
                this.aliasMap.put(alias, name);
            }
        }
    }
}

2.3.2 解析alias标签

在对bean进行定义时, 除了使用bean标签中的id或者name属性来指定名称外, 可以使用alias标签提供多个名称, 例如以下配置

<bean id="classA" name="classA1" class="com.ClassA" />
<bean id="classB" class="com.ClassB" />
<alias name="classB" alias="classB1,classB2" />

接下来回到DefaultBeanDefinitionDocumentReader的parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)方法中, 详细看下processAliasRegistration(ele);方法时如何解析的.

public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
    protected void processAliasRegistration(Element ele) {
        // 获取beanName
        String name = ele.getAttribute(NAME_ATTRIBUTE);
        // 获取alias
        String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
        boolean valid = true;
        if (!StringUtils.hasText(name)) {
            getReaderContext().error("Name must not be empty", ele);
            valid = false;
        }
        if (!StringUtils.hasText(alias)) {
            getReaderContext().error("Alias must not be empty", ele);
            valid = false;
        }
        if (valid) {
            try {
                // 注册alias
                // 此处获取的AliasRegistry其实是DefaultListableBeanFactory, 可以查看创建XmlBeanDefinitionReader时的代码.
                getReaderContext().getRegistry().registerAlias(name, alias);
            } catch (Exception ex) {
                getReaderContext().error("Failed to register alias '" + alias + "' for bean with name '" + name + "'", ele, ex);
            }
            // 注册完成后通知监听器做响应的处理.
            getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
        }
    }
}

2.3.3 解析import标签

public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
    protected void importBeanDefinitionResource(Element ele) {
        // 获取resource属性
        String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
        if (!StringUtils.hasText(location)) {
            getReaderContext().error("Resource location must not be empty", ele);
            return;
        }
        // 解析系统属性, 比如${user.dir}
        location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);
        Set<Resource> actualResources = new LinkedHashSet<>(4);
        // 判断location是绝对路径还是相对路径
        boolean absoluteLocation = false;
        try {
            absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
        } catch (URISyntaxException ex) {
        }
        
        if (absoluteLocation) {
            // 绝对路径, 根绝地址加载相应的配置文件
            try {
                // 回到loadBeanDefinitions方法, 重复加载 -> 解析 -> 注册的逻辑
                int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
            } catch (BeanDefinitionStoreException ex) {
                getReaderContext().error("Failed to import bean definitions from URL location [" + location + "]", ele, ex);
            }
        } else {
            // 相对路径, 根据相对路径计算出绝对路径
            try {
                int importCount;
                // 
                Resource relativeResource = getReaderContext().getResource().createRelative(location);
                if (relativeResource.exists()) {
                    // 回到loadBeanDefinitions方法, 重复加载 -> 解析 -> 注册的逻辑
                    importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
                    actualResources.add(relativeResource);
                } else {
                    String baseLocation = getReaderContext().getResource().getURL().toString();
                    // 回到loadBeanDefinitions方法, 重复加载 -> 解析 -> 注册的逻辑
                    importCount = getReaderContext().getReader().loadBeanDefinitions(
                            StringUtils.applyRelativePath(baseLocation, location), actualResources);
                }
            } catch (IOException ex) {
                getReaderContext().error("Failed to resolve current resource location", ele, ex);
            } catch (BeanDefinitionStoreException ex) {
                getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]", ele, ex);
            }
        }
        // 解析后进行监听器激活处理
        Resource[] actResArray = actualResources.toArray(new Resource[0]);
        getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
    }
    
}

2.3.4 解析beans标签

对于嵌入式beans标签来说, 与单独的配置文件并没有太大的区别, 在DefaultBeanDefinitionDocumentReader的parseDefaultElement方法中就是直接调用doRegisterBeanDefinitions(ele), 递归调用beans的解析过程, 此处不再赘述.

2.4 解析自定义标签

默认标签解析完成之后, 接下来就开始分析自定义标签的处理过程了. 在分析代码之前先看下如何使用自定义标签, 大致可以分为以下几个步骤:

  1. 创建一个需要扩展的组件
  2. 定义一个XSD文件描述组件内容
  3. 创建BeanDefinitionParser的子类(一般继承AbstractSingleBeanDefinitionParser), 用来解析XSD文件中的定义和组件定义.
  4. 创建NamespaceHandler的子类(一般继承NamespaceHandlerSupport), 目的是将组件注册到Spring容器中.
  5. 编写Spring.handlers和Spring.schemas文件

现在回到DefaultBeanDefinitionDocumentReader的parseBeanDefinitions方法内, 当遇到XML中非默认标签时, 会调用delegate.parseCustomElement(ele)这行代码, 我们从这里开始分析.

public class BeanDefinitionParserDelegate {
    @Nullable
    public BeanDefinition parseCustomElement(Element ele) {
        return parseCustomElement(ele, null);
    }

    @Nullable
    public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
        // 获取对应的命名空间
        String namespaceUri = getNamespaceURI(ele);
        if (namespaceUri == null) {
            return null;
        }
        // 根据命名空间找到对应的NamespaceHandler
        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));
    }
}

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
    public XmlReaderContext createReaderContext(Resource resource) {
        return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
                this.sourceExtractor, this, getNamespaceHandlerResolver());
    }
    
    public NamespaceHandlerResolver getNamespaceHandlerResolver() {
        if (this.namespaceHandlerResolver == null) {
            this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
        }
        return this.namespaceHandlerResolver;
    }
    protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
        ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader());
        return new DefaultNamespaceHandlerResolver(cl);
    }
}

上述代码中, 通过标签的命名空间然后获取NamespaceHandler. 在XmlReaderContext初始化的时候, namespaceHandlerResolver属性已经初始化为DefaultNamespaceHandlerResolver, 在分析resolve方法前, 先了解下Spring.handlers中的内容.

http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler
http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler
http\://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler
http\://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler

上述内容截取自spring-context.jar的spring.handlers文件中, 其实就是一个properties文件, 记录了命名空间与处理器之间的映射关系, 其中namespace为key, NamespaceHandler处理器为value.

2.4.1 NamespaceHandler

public class DefaultNamespaceHandlerResolver implements NamespaceHandlerResolver {
    public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";
    
    private final String handlerMappingsLocation;

    private volatile Map<String, Object> handlerMappings;
    
    public DefaultNamespaceHandlerResolver() {
        this(null, DEFAULT_HANDLER_MAPPINGS_LOCATION);
    }
    
    public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader) {
        this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION);
    }
    
    public NamespaceHandler resolve(String namespaceUri) {
        // 获取所有已经配置的handler映射
        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对象, 并且实例化
                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("Could not find NamespaceHandler class [" + className +
                        "] for namespace [" + namespaceUri + "]", ex);
            } catch (LinkageError err) {
                throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" +
                        className + "] for namespace [" + namespaceUri + "]", err);
            }
        }
    }
    // 读取Spring.handlers配置文件并将配置文件缓存在map中
    private Map<String, Object> getHandlerMappings() {
        Map<String, Object> handlerMappings = this.handlerMappings;
        if (handlerMappings == null) {
            synchronized (this) {
                handlerMappings = this.handlerMappings;
                if (handlerMappings == null) {
                    try {
                        // 读取文件填充到Properties中
                        Properties mappings = PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
                        handlerMappings = new ConcurrentHashMap<>(mappings.size()); 
                        CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings); // 合并
                        this.handlerMappings = handlerMappings;
                    } catch (IOException ex) {
                        throw new IllegalStateException("Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex);
                    }
                }
            }
        }
        return handlerMappings;
    }
}

DefaultNamespaceHandlerResolver中的代码比较简单: 文件中读取内容, 根据类名反射并实例化NamespaceHandler. 之后调用其init方法, 注册一个或多个BeanDefinitionParser的实现类, 用于解析标签.

2.4.2 标签解析

回到BeanDefinitionParserDelegate的parseCustomElement方法中, 获取到NamespaceHandler之后, Spring调用NamespaceHandler的parse方法, 将解析的工作委托给了自定义的解析器去解析. 这里我们分析下NamespaceHandlerSupport中的parse方法.

public abstract class NamespaceHandlerSupport implements NamespaceHandler {
    private final Map<String, BeanDefinitionParser> parsers = new HashMap<>();
    // 自定义的NamespaceHandler中init方法中一般都会调用该方法注册BeanDefinitionParser
    protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) {
        this.parsers.put(elementName, parser);
    }

    public BeanDefinition parse(Element element, ParserContext parserContext) {
        // 寻找解析器进行解析
        BeanDefinitionParser parser = findParserForElement(element, parserContext);
        return (parser != null ? parser.parse(element, parserContext) : null);
    }
    
    private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
        // 获取元素名称, 比如<context:component-scan />中的component-scan
        String localName = parserContext.getDelegate().getLocalName(element);
        // 根据component-scan找到对应的解析器
        BeanDefinitionParser parser = this.parsers.get(localName);
        if (parser == null) {
            parserContext.getReaderContext().fatal("Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
        }
        return parser;
    }
}

在我们自定义的NamespaceHandler中init的方法内, 一般会调用registerBeanDefinitionParser方法注册一个或多个BeanDefinitionParser, 比如在Spring中解析<context:component-scan />时使用的ContextNamespaceHandler类.

public class ContextNamespaceHandler extends NamespaceHandlerSupport {

    @Override
    public void init() {
        registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
        registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
        registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
        registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
        registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
        registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
        registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
        registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
    }
}

所以在findParserForElement时, 可以根据标签名找到对应的BeanDefinitionParser, Spring将标签的解析工作继续委托给了BeanDefinitionParser处理.

public abstract class AbstractBeanDefinitionParser implements BeanDefinitionParser {

    public static final String ID_ATTRIBUTE = "id";
    public static final String NAME_ATTRIBUTE = "name";
    // 虽说parse方法是对自定义配置文件的解析, 但是这个函数大部分代码是用来处理解析后的AbstractBeanDefinition,
    // 真正做解析的方法还是委托给了需要子类实现的parseInternal方法.
    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(...);
                }
                String[] aliases = null;
                if (shouldParseNameAsAliases()) {
                    String name = element.getAttribute(NAME_ATTRIBUTE);
                    if (StringUtils.hasLength(name)) {
                        aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name));
                    }
                }
                // 将AbstractBeanDefinition转换为BeanDefinitionHolder并注册
                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) {
                String msg = ex.getMessage();
                parserContext.getReaderContext().error((msg != null ? msg : ex.toString()), element);
                return null;
            }
        }
        return definition;
    }

    protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) throws BeanDefinitionStoreException {
        if (shouldGenerateId()) {
            return parserContext.getReaderContext().generateBeanName(definition);
        } else {
            String id = element.getAttribute(ID_ATTRIBUTE);
            if (!StringUtils.hasText(id) && shouldGenerateIdAsFallback()) {
                id = parserContext.getReaderContext().generateBeanName(definition);
            }
            return id;
        }
    }
    
    protected abstract AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext);
}

public abstract class AbstractSingleBeanDefinitionParser extends AbstractBeanDefinitionParser {
    // 在parseInternal中并不是直接调用doParse方法, 而是进行一系列的数据准备, 包括beanClass、scope等等
    protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
        String parentName = getParentName(element);
        if (parentName != null) {
            builder.getRawBeanDefinition().setParentName(parentName);
        }
        // 获取自定义标签中的class属性, 子类可以覆盖getBeanClass或者getBeanClassName方法进行设定class属性
        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));
        BeanDefinition containingBd = parserContext.getContainingBeanDefinition();
        if (containingBd != null) {
            // 若存在父类, 使用父类的scope属性
            builder.setScope(containingBd.getScope());
        }
        if (parserContext.isDefaultLazyInit()) {
            // 配置延迟加载
            builder.setLazyInit(true);
        }
        // 调用子类的doParse方法进行解析
        doParse(element, parserContext, builder);
        return builder.getBeanDefinition();
    }
    
    protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
        doParse(element, builder);
    }
    protected void doParse(Element element, BeanDefinitionBuilder builder) {}
}

以上就是自定义标签的解析. 在自定义的BeanDefinitionParser中, 如果继承自AbstractSingleBeanDefinitionParser, 只需要在doParse方法中实现与自己业务逻辑相关的部分即可. 创建BeanDefinition以及进行相应默认属性的设置, 对于这些工作Spring都已经帮我们实现了, 只是暴露了一些接口来供用户实现个性化的业务.

3. 总结

以上就是本文的所有内容了, 以XmlBeanFactory为入口, 分析了Spring如何解析XML配置, 包括默认标签和自定义标签. 后续的文章会继续分析在Spring中如何加载bean. bean的加载会比XML的解析更加的复杂, 也需要更多的时间去理解.

posted on 2021-02-18 14:44  annwyn  阅读(109)  评论(0)    收藏  举报

导航