这块主要讲 Docoment 对象中的各种标签解析成 BeanDefinition ,并且缓存到 BeanFactory 中。
解析得到 BeanDefinition
接下来,才正式的进入 Bean 的注册环节;这个时候使用 DefaultBeanDefinitionDocumentReader 来处理注册相关件逻辑;
@Overridepublic void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {this.readerContext = readerContext;doRegisterBeanDefinitions(doc.getDocumentElement());}
解析 XML 结点,DefaultBeanDefinitionDocumentReader # doRegisterBeanDefinitions(Element root);
protected void doRegisterBeanDefinitions(Element root) {// 如果有嵌套的bean定义那么就会引起递归的调用// 为了保留默认属性及传播默认属性,保留当前父节点(可能为空)BeanDefinitionParserDelegate parent = this.delegate;// delegate:代表,相当于克隆了一份当前结点,并且还记录了父节点this.delegate = createDelegate(getReaderContext(), root, parent);// 判断当前结点的命名空间是否为默认的 http://www.springframework.org/schema/beans// 根结点才有这个属性,例如:<beans xmlns="http://www.springframework.org/schema/beans"> ...</beans>if (this.delegate.isDefaultNamespace(root)) {String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);if (StringUtils.hasText(profileSpec)) {// 可能有多个profile,进行切分String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);// We cannot use Profiles.of(...) since profile expressions are not supported// in XML config. See SPR-12458 for details.// 如果当前启动环境不匹配设置的任何profile,则不注册beanDefinitionif (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {if (logger.isDebugEnabled()) {logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +"] not matching: " + getReaderContext().getResource());}return;}}}// 预处理,空实现,留给后人preProcessXml(root);// 解析处理parseBeanDefinitions(root, this.delegate);// 后处理,空实现,留给后人postProcessXml(root);// 恢复原始值this.delegate = parent;}
然后就会进入 DefaultBeanDefinitionDocumentReader # parseBeanDefinitions(root, this.delegate);
接下来的解析就分成了解析系统默认的标签以及自定义的标签解析。
- 默认标签包括:import、alias、bean、beans;
- 自定义的标签比如:aop 、tx 这些都属于自定义标签。
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {// 默认的命名空间,http://www.springframework.org/schema/beansif (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);}}
