这块主要讲 Docoment 对象中的各种标签解析成 BeanDefinition ,并且缓存到 BeanFactory 中。

解析得到 BeanDefinition

接下来,才正式的进入 Bean 的注册环节;这个时候使用 DefaultBeanDefinitionDocumentReader 来处理注册相关件逻辑;

  1. @Override
  2. public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
  3. this.readerContext = readerContext;
  4. doRegisterBeanDefinitions(doc.getDocumentElement());
  5. }

解析 XML 结点,DefaultBeanDefinitionDocumentReader # doRegisterBeanDefinitions(Element root);

  1. protected void doRegisterBeanDefinitions(Element root) {
  2. // 如果有嵌套的bean定义那么就会引起递归的调用
  3. // 为了保留默认属性及传播默认属性,保留当前父节点(可能为空)
  4. BeanDefinitionParserDelegate parent = this.delegate;
  5. // delegate:代表,相当于克隆了一份当前结点,并且还记录了父节点
  6. this.delegate = createDelegate(getReaderContext(), root, parent);
  7. // 判断当前结点的命名空间是否为默认的 http://www.springframework.org/schema/beans
  8. // 根结点才有这个属性,例如:<beans xmlns="http://www.springframework.org/schema/beans"> ...</beans>
  9. if (this.delegate.isDefaultNamespace(root)) {
  10. String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
  11. if (StringUtils.hasText(profileSpec)) {
  12. // 可能有多个profile,进行切分
  13. String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
  14. profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
  15. // We cannot use Profiles.of(...) since profile expressions are not supported
  16. // in XML config. See SPR-12458 for details.
  17. // 如果当前启动环境不匹配设置的任何profile,则不注册beanDefinition
  18. if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
  19. if (logger.isDebugEnabled()) {
  20. logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
  21. "] not matching: " + getReaderContext().getResource());
  22. }
  23. return;
  24. }
  25. }
  26. }
  27. // 预处理,空实现,留给后人
  28. preProcessXml(root);
  29. // 解析处理
  30. parseBeanDefinitions(root, this.delegate);
  31. // 后处理,空实现,留给后人
  32. postProcessXml(root);
  33. // 恢复原始值
  34. this.delegate = parent;
  35. }

然后就会进入 DefaultBeanDefinitionDocumentReader # parseBeanDefinitions(root, this.delegate);
接下来的解析就分成了解析系统默认的标签以及自定义的标签解析。

  1. 默认标签包括:import、alias、bean、beans;
  2. 自定义的标签比如:aop 、tx 这些都属于自定义标签。
    1. protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    2. // 默认的命名空间,http://www.springframework.org/schema/beans
    3. if (delegate.isDefaultNamespace(root)) {
    4. NodeList nl = root.getChildNodes();
    5. // 遍历子节点
    6. for (int i = 0; i < nl.getLength(); i++) {
    7. Node node = nl.item(i);
    8. if (node instanceof Element) {
    9. Element ele = (Element) node;
    10. if (delegate.isDefaultNamespace(ele)) {
    11. parseDefaultElement(ele, delegate);
    12. } else {
    13. delegate.parseCustomElement(ele);
    14. }
    15. }
    16. }
    17. } else {
    18. // 如果没有使用系统自带的标签属性,就需要自定义解析的方法
    19. delegate.parseCustomElement(root);
    20. }
    21. }