spring-beanFactory一

下面以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。

原文地址:https://www.cnblogs.com/holoyong/p/7363747.html