Spring bean的初始化源码分析-XML解析
XML解析部分,XML解析最终会将XML中配置的bean或者标签需要扫描的bean,都准备好,生成beanDefinition,用于后续的bean实例化
XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("/spring-code-test.xml"));
DefaultListableBeanFactory 类是 spring bean 加载的核心类, XMLBeanFactory继承,实际是在里面封装了另一个类XmlBeanDefinitionReader, 这个类用于解析xml。本节主要讲这个类如何解析XML的。
public class XmlBeanFactory extends DefaultListableBeanFactory { private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this); public XmlBeanFactory(Resource resource) throws BeansException { this(resource, null); } public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) { super(parentBeanFactory); this.reader.loadBeanDefinitions(resource); } }
实际XML的加载过程封装在 XmlBeanDefinitionReader.loadBeanDefinitions 方法里了,实际过程是
1. 先对 输入的 文件进行 Resource 封装, new ClassPathResource("/spring-code-test.xml"), Resource对象传入XmlBeanDefinitionReader
2. XmlBeanDefinitionReader
2.1 对输入对象进行encoding封装
2.2 获取XML的验证模式,同时确认解析标签使用的XSD文档和对应标签解析的jar路径)
2.3 加载XML文件,得到对应的Document对象
// XmlBeanDefinitionReader public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { ...... try { InputStream inputStream = encodedResource.getResource().getInputStream(); try { InputSource inputSource = new InputSource(inputStream); if (encodedResource.getEncoding() != null) { inputSource.setEncoding(encodedResource.getEncoding()); } return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); } ...... } protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) { try { // XML 生成 document对象,doLoadDocument 内部会确认 XSD文档和解析标签所使用的jar包 Document doc = doLoadDocument(inputSource, resource); return registerBeanDefinitions(doc, resource); } } public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { // 实际负责加载的document的类是 DefaultBeanDefinitionDocumentReader BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); int countBefore = getRegistry().getBeanDefinitionCount(); documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; }
DefaultBeanDefinitionDocumentReader 类做的事情就是根据 document ,进行element解析
// DefaultBeanDefinitionDocumentReader 类 public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { this.readerContext = readerContext; logger.debug("Loading bean definitions"); // 获取root节点,进行解析 Element root = doc.getDocumentElement(); doRegisterBeanDefinitions(root); } /** * Parse the elements at the root level in the document: * "import", "alias", "bean". * @param root the DOM root element of the document */ // 解析具体实现方法 protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { 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); } } // 解析默认标签,bean标签相关 protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // Register the final decorated instance. BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex); } // Send registration event. getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }