下面以XmlBeanFactory为例来简单看一下beanFactory对xml的处理过程。
1 ResourceLoader resourceLoader = new DefaultResourceLoader(); 2 //ResourceLoader类似一个工厂,getResource可以通过传入的路径判断返回什么类型的Resource, 3 //比如,如果路径以classpath:开头就会返回一个代表该路径的ClassPathResource实例 4 org.springframework.core.io.Resource resource = resourceLoader.getResource("spring/spring-test.xml"); 5 XmlBeanFactory factory = new XmlBeanFactory(resource);
1 public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException { 2 super(parentBeanFactory); 3 //private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this); 4 //这里只看到Resource,具体Resource由实现决定,beanFactory关注Resource的getInputStream, 5 //比如ClassPathResource的getInputStream是return this.clazz.getResourceAsStream(this.path)这种形式, 6 //FileSystemResource的getInputStream是new FileInputStream(this.file)这种形式, 7 //策略模式 8 this.reader.loadBeanDefinitions(resource); 9 }
1 @Override 2 public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException { 3 //EncodedResource只是给Resource设定解码字符集,在使用reader时会用到,直接处理InputStream字节流时不会涉及 4 return loadBeanDefinitions(new EncodedResource(resource)); 5 }
1 //loadBeanDefinitions的主要逻辑,有删减 2 public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { 3 InputStream inputStream = encodedResource.getResource().getInputStream(); 4 InputSource inputSource = new InputSource(inputStream); 5 if (encodedResource.getEncoding() != null) { 6 inputSource.setEncoding(encodedResource.getEncoding()); 7 } 8 return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); 9 }
1 //doLoadBeanDefinitions的主要逻辑,有删减 2 protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) 3 throws BeanDefinitionStoreException { 4 //org.w3c.dom.Document 5 Document doc = doLoadDocument(inputSource, resource); 6 //注册bean definition,还未实例化 7 return registerBeanDefinitions(doc, resource); 8 }
1 //doLoadDocument会调用DefaultDocumentLoader的loadDocument方法,根据xml文件是否存在DOCTYPE决定validationMode(DTD、XSD) 2 public Document loadDocument(InputSource inputSource, EntityResolver entityResolver, 3 ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception { 4 //javax.xml.parsers.DocumentBuilderFactory.newInstance(),以及对DocumentBuilderFactory的一些简单配置,如setValidating 5 DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware); 6 //javax.xml.parsers.DocumentBuilder builder=factory.newDocumentBuilder() 7 DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler); 8 //解析得到org.w3c.dom.Document 9 return builder.parse(inputSource); 10 }
1 //registerBeanDefinitions就是通过document注册bean定义,有删减 2 public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { 3 this.readerContext = readerContext; 4 //delegate是BeanDefinitionParserDelegate用于解析xml bean definitions 5 this.delegate = createDelegate(getReaderContext(), root, parent); 6 Element root = doc.getDocumentElement(); 7 NodeList nl = root.getChildNodes(); 8 for (int i = 0; i < nl.getLength(); i++) { 9 Node node = nl.item(i); 10 if (node instanceof Element) { 11 Element ele = (Element) node; 12 if (delegate.isDefaultNamespace(ele)) { 13 //解析逻辑主要就是将使用delegate将ele解析为beanDefinition,并将beanDefinition注册在beanFactory的注册表上(其实就是map) 14 parseDefaultElement(ele, delegate); 15 } 16 else { 17 delegate.parseCustomElement(ele); 18 } 19 } 20 } 21 }
至此,spring的xml配置文件就变成了beanFactroy中注册表中的bean definitions。