2_XML形式bean的解析

在Spring中,注册一个bean分为两个方式,一个是通过注解扫描的方式,一个是通过xml的方式。下面我们就针对Spring的xml方式注册解析bean的过程进行分析

通过跟踪代码进入AbstractApplicationContext类refresh方法

在refresh方法中调用了obtainFreshBeanFactory();上篇文章提到过该类。该类是用来获取对应的beanFactory的。但是对于ClassPathXmlApplicationContext来说,他还在此进行解析了xml注册相关bean的动作。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {

                   refreshBeanFactory();

                   ConfigurableListableBeanFactory beanFactory = getBeanFactory();

                   if (logger.isDebugEnabled()) {

                            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);

                   }

                   return beanFactory;

         }

进入AbstractRefreshableApplicationContext的refreshBeanFactory();方法

protected final void refreshBeanFactory() throws BeansException {

        //判断当前beanFactory是否为空。如果为空进行销毁关闭beanFactory

                   if (hasBeanFactory()) {

                            destroyBeans();

                            closeBeanFactory();

                   }

                   try {

           //创建一个默认的BeanFactory。New  DefaultListableBeanFactory

                            DefaultListableBeanFactory beanFactory = createBeanFactory();

                            beanFactory.setSerializationId(getId());

            //设置是否允许循环引用

                            customizeBeanFactory(beanFactory);

            //解析xml并且注册bean

                            loadBeanDefinitions(beanFactory);

                            synchronized (this.beanFactoryMonitor) {

                                     this.beanFactory = beanFactory;

                            }

                   }

                   catch (IOException ex) {

                            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);

                   }

         }

进入AbstractXmlApplicationContext中的loadBeanDefinitions方法。代码如下

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {

                   //创建一个xml reader用来解析xml

                   XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

 

                   //设置相应属性

                   beanDefinitionReader.setEnvironment(this.getEnvironment());

                   beanDefinitionReader.setResourceLoader(this);

                   beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

        //初始化bean reader,其实只是设置了是否检验这个参数

                   initBeanDefinitionReader(beanDefinitionReader);

        //根据beanReader进行加载bean的定义

                   loadBeanDefinitions(beanDefinitionReader);

         }

 

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {

       //根据resouce进行解析

                   Resource[] configResources = getConfigResources();

                   if (configResources != null) {

                            reader.loadBeanDefinitions(configResources);

                   }

        //根据文件进行解析。

                   String[] configLocations = getConfigLocations();

                   if (configLocations != null) {

                            reader.loadBeanDefinitions(configLocations);

                   }

         }

进入AbstractBeanDefinitionReader的loadBeanDefinitions方法

public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {

                   Assert.notNull(resources, "Resource array must not be null");

                   int counter = 0;

       // 遍历所有的资源文件,进行逐一解析

                   for (Resource resource : resources) {

                            counter += loadBeanDefinitions(resource);

                   }

       //返回加载的bean的个数

                   return counter;

         }

进入XmlBeanDefinitionReader的loadBeanDefinitions方法中

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {

                   Assert.notNull(encodedResource, "EncodedResource must not be null");

                   if (logger.isInfoEnabled()) {

                            logger.info("Loading XML bean definitions from " + encodedResource.getResource());

                   }

 

                   Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();

                   if (currentResources == null) {

                            currentResources = new HashSet<EncodedResource>(4);

                            this.resourcesCurrentlyBeingLoaded.set(currentResources);

                   }

       //防止循环引入。

                   if (!currentResources.add(encodedResource)) {

                            throw new BeanDefinitionStoreException(

                                               "Detected cyclic loading of " + encodedResource + " - check your import definitions!");

                   }

                   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());

                            }

                            finally {

                                     inputStream.close();

                            }

                   }

                   catch (IOException ex) {

                            throw new BeanDefinitionStoreException(

                                               "IOException parsing XML document from " + encodedResource.getResource(), ex);

                   }

                   finally {

                            currentResources.remove(encodedResource);

                            if (currentResources.isEmpty()) {

                                     this.resourcesCurrentlyBeingLoaded.remove();

                            }

                   }

         }

进入doLoadBeanDefinitions,其实当前类也没做什么。就是通过api解析出Document。然后再根据Document 进行解析。

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)

                            throws BeanDefinitionStoreException {

                   try {

                            Document doc = doLoadDocument(inputSource, resource);

                            return registerBeanDefinitions(doc, resource);

                   }

                   catch (BeanDefinitionStoreException ex) {

                            throw ex;

                   }

                   catch (SAXParseException ex) {

                            throw new XmlBeanDefinitionStoreException(resource.getDescription(),

                                               "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);

                   }

                   catch (SAXException ex) {

                            throw new XmlBeanDefinitionStoreException(resource.getDescription(),

                                               "XML document from " + resource + " is invalid", ex);

                   }

                   catch (ParserConfigurationException ex) {

                            throw new BeanDefinitionStoreException(resource.getDescription(),

                                               "Parser configuration exception parsing XML from " + resource, ex);

                   }

                   catch (IOException ex) {

                            throw new BeanDefinitionStoreException(resource.getDescription(),

                                              "IOException parsing XML document from " + resource, ex);

                   }

                   catch (Throwable ex) {

                            throw new BeanDefinitionStoreException(resource.getDescription(),

                                               "Unexpected exception parsing XML document from " + resource, ex);

                   }

         }

进入registerBeanDefinitions

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {

                   BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();

                   int countBefore = getRegistry().getBeanDefinitionCount();

                   documentReader.registerBeanDefinitions(doc, createReaderContext(resource));

                   return getRegistry().getBeanDefinitionCount() - countBefore;

         }

进入DefaultBeanDefinitionDocumentReader的doRegisterBeanDefinitions

protected void doRegisterBeanDefinitions(Element root) {

                  

                   BeanDefinitionParserDelegate parent = this.delegate;

                   this.delegate = createDelegate(getReaderContext(), root, parent);

        //查找profile元素。

                   if (this.delegate.isDefaultNamespace(root)) {

                            String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);

                            if (StringUtils.hasText(profileSpec)) {

                                     String[] specifiedProfiles = StringUtils.tokenizeToStringArray(

                                                        profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);

                                     if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {

                                               if (logger.isInfoEnabled()) {

                                                        logger.info("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;

         }

进入parseBeanDefinitions

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {

       //判断是否是默认的 schema是下面的。

       // http://www.springframework.org/schema/beans

                   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 {

           //解析定制的customeElemenet.自定义标签的解析入口

                            delegate.parseCustomElement(root);

                   }

         }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值