国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Spring源碼閱讀——ClassPathXmlApplicationContext(四)

wmui / 3072人閱讀

摘要:在的方法中,遍歷每一個節點,判斷是否為默認命名空間中的節點,如果是非默認命名空間的,調用方法進行處理。在學習自定義標簽解析之前,先寫一個自定義標簽的。

在DefaultBeanDefinitionDocumentReader的parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)方法中,遍歷每一個節點,判斷是否為默認命名空間中的節點,如果是非默認命名空間的,調用delegate.parseCustomElement(ele)方法進行處理。在學習自定義標簽解析之前,先寫一個自定義標簽的demo。

一、自定義標簽示例

定義POJO

下面定義一個Person類

package com.demo.beans.custom;

/**
 *@author zhzhd
 *@date 2018/6/11
 *@package 
 *@describe
 **/
public class Person {
    private String userName;
    private String sex;
    private Integer age;

    public Person(String name){
        this.userName = name;
    }
   ......省略setter和getter
}

定義一個文件描述組件

在webapp下創建person.xsd文件,內容如下:



    
        
            
                
                    
                
            
        
        
            
                
                    
                
            
        
        
            
                
                    
                
            
        
        
            
                
                    
                
            
        
    

    
        
            
        
    

自定義NamespaceHandler

自定義MyNamespaceHandler,繼承NamespaceHandlerSupport,并且重寫init()方法,實現如下:

package com.demo.beans.custom;

import org.springframework.beans.factory.xml.NamespaceHandlerSupport;

/**
 *@author zhzhd
 *@date 2018/6/11
 *@package com.demo.beans.custom
 *@describe
 **/
public class MyNamespaceHandler extends NamespaceHandlerSupport{
    public void init() {
        registerBeanDefinitionParser("", new PersonBeanDefinitionParser());
    }
}

實現自定義PersonBeanDefinitionParser

自定義實現PersonBeanDefinitionParser,并且重寫Class getBeanClass(Element element)和doParse(Element element, BeanDefinitionBuilder bean)方法。getBeanClass方法返回當前bean的class,doParse解析自定義元素屬性,實現如下:

package com.demo.beans.custom;

import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;

/**
 *@author zhzhd
 *@date 2018/6/11
 *@package com.demo.beans.custom
 *@describe
 **/
public class PersonBeanDefinitionParser extends AbstractSingleBeanDefinitionParser{

    @Override
    protected Class getBeanClass(Element element){
        return Person.class;
    }

    @Override
    protected void doParse(Element element, BeanDefinitionBuilder bean){
        String name = element.getAttribute("name");
        bean.addConstructorArgValue(name);
        if (StringUtils.hasText(name)){
            bean.addConstructorArgValue(name);
        }

        String age = element.getAttribute("age");
        String sex = element.getAttribute("sex");
        if (StringUtils.hasText(age)){
            bean.addPropertyValue("age", Integer.parseInt(age));
        }
        if (StringUtils.hasText(age)){
            bean.addPropertyValue("sex", sex);
        }
    }
}

創建spring.handlers和spring.schemas

http://www.zhzhd.com/schema/person=com.demo.beans.custom.MyNamespaceHandler
http://www.zhzhd.com/schema/person.xsd=person.xsd

在XML中配置bean以及測試

接下來,需要在spring的配置文件中加入命名空間信息,并且配置自定義bean,實現如下:



    

測試demo如下:

    public static void main(String[] args) {
        BeanFactory beanFactory1 = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
        ApplicationContext beanFactory = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"},true);
        Person person = beanFactory.getBean("testPerson", Person.class);
        System.out.println(JSON.toJSONString(person));
    }

從上面的示例可以看到,我們定義了自定義節點的handler,spring在解析xml中節點或屬性的時候,當遇到自定義節點和屬性時,會調用響應的handler進行解析,下面具體分析自定義節點和屬性解析的源碼。

二、spring解析自定義標簽的源碼分析

首先,從xml元素的解析開始分析,在parseBeanDefinitions()方法中,判斷如果是xml中節點或屬性是自定義的,則調用BeanDefinitionParserDelegate的parseCustomElement()方法處理,下面是parseCustomElement()的實現:

    public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
        // 讀取命名空間url
        String namespaceUri = getNamespaceURI(ele);
        if (namespaceUri == null) {
            return null;
        }
        // 解析命名空間,返回NamespaceHandler實例
        NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
        if (handler == null) {
            error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
            return null;
        }
        // 解析自定義標簽
        return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
    }

從Element中獲取到自定義命名空間uri后,交給DefaultNamespaceHandlerResolver的resolve()方法解析并實例化NamespaceHandler實例,具體實現如下:

public NamespaceHandler resolve(String namespaceUri) {
        // 獲取命名空間uri和handler類名關系map
        Map handlerMappings = getHandlerMappings();
        // 獲取類名
        Object handlerOrClassName = handlerMappings.get(namespaceUri);
        if (handlerOrClassName == null) {
            return null;
        }
        else if (handlerOrClassName instanceof NamespaceHandler) {
            return (NamespaceHandler) handlerOrClassName;
        }
        else {
            String className = (String) handlerOrClassName;
            try {
                Class handlerClass = ClassUtils.forName(className, this.classLoader);
                if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
                    throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
                            "] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
                }
                // 實例化NamespaceHandler
                NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
                // 初始化NamespaceHandler
                namespaceHandler.init();
                handlerMappings.put(namespaceUri, namespaceHandler);
                return namespaceHandler;
            }
            catch (ClassNotFoundException ex) {
                throw new FatalBeanException("Could not find NamespaceHandler class [" + className +
                        "] for namespace [" + namespaceUri + "]", ex);
            }
            catch (LinkageError err) {
                throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" +
                        className + "] for namespace [" + namespaceUri + "]", err);
            }
        }
    }

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/69740.html

相關文章

  • Spring源碼閱讀——ClassPathXmlApplicationContext

    摘要:在的方法中,遍歷每一個節點,判斷是否為默認命名空間中的節點,如果是非默認命名空間的,調用方法進行處理。在學習自定義標簽解析之前,先寫一個自定義標簽的。 在DefaultBeanDefinitionDocumentReader的parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)方法中,遍歷每一...

    silenceboy 評論0 收藏0
  • Spring源碼閱讀——ClassPathXmlApplicationContext

    摘要:在的方法中,遍歷每一個節點,判斷是否為默認命名空間中的節點,如果是非默認命名空間的,調用方法進行處理。在學習自定義標簽解析之前,先寫一個自定義標簽的。 在DefaultBeanDefinitionDocumentReader的parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)方法中,遍歷每一...

    ixlei 評論0 收藏0
  • Spring源碼閱讀——ClassPathXmlApplicationContext(一)

    摘要:的繼承關系繼承了,實現了接口。是所有容器的頂級接口,中所有容器都是基于的。方法創建一個新的容器。在本方法中,最重要的是,調用這個方法解析配置文件,注冊。 ClassPathXmlApplicationContext的繼承關系 ClassPathXmlApplicationContext繼承了AbstractXmlApplicationContext,實現了ApplicationCont...

    taowen 評論0 收藏0
  • Spring源碼閱讀——ClassPathXmlApplicationContext(三)

    摘要:在上一篇源碼閱讀二文章的最后,需要解析元素,創建實例完成必須的裝配和進行最終的注冊來完成元素的解析和注冊,下面分別閱讀三步的源碼。 在上一篇Spring源碼閱讀——ClassPathXmlApplicationContext(二)文章的最后,需要解析bean元素,創建BeanDefinitionHolder實例、完成必須的裝配和進行最終的注冊bean來完成bean元素的解析和注冊,下面...

    xbynet 評論0 收藏0
  • Spring源碼閱讀——ClassPathXmlApplicationContext(三)

    摘要:在上一篇源碼閱讀二文章的最后,需要解析元素,創建實例完成必須的裝配和進行最終的注冊來完成元素的解析和注冊,下面分別閱讀三步的源碼。 在上一篇Spring源碼閱讀——ClassPathXmlApplicationContext(二)文章的最后,需要解析bean元素,創建BeanDefinitionHolder實例、完成必須的裝配和進行最終的注冊bean來完成bean元素的解析和注冊,下面...

    AndroidTraveler 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<