《spring设计思想》20-自定义xml的Namespace-自定义命名空间

上一节的xml解析成BeanDefinition中讲到了

XmlBeanDefinitionReader 委托DefaultBeanDefinitionDocumentReader 来解析xml文件

DefaultBeanDefinitionDocumentReader 委托 NamespaceHandler 来解析Document的Element

NamespaceHandler 委托 BeanDefinitionParser 来解析Element中的tag,

那么这次我们尝试自己命名一个dubbo类似的命名空间,暂时取名

其实自定义命名空间及实现,需要做以下几步:

1:声明命名空间,创建xsd文件

2:创建spring.schames文件。指定命名空间的xsd路径,

3:自定义实现命名空间的处理器-CustomNamespaceHandler,并创建spring.handlers指定该处理器

4:自定义实现的BeanDefinition解析器 CustomBeanDefinitionParser。并注册到customNamespaceHandler中。

5:配置的资源文件,

6:启动测试。

我们按照上面的步骤,简单的实现一下

第一步:首先创建一个简单的maven工程,spring-custom-namespace。添加基础依赖 spring-beans

第二步:在src目录中新建custom.xsd,然后模仿spring-beans.xsd文件的格式描写自己的标签

xsd主要有几个要素 1:xmlns/targetNamespace,2





    

    
    
        
            
            
        
    


    
        
        
        
        
        
        
    

    


自定义schema xmlns ,写一个属于自己的路径。注意xmlns 跟targetNamespace 的配置要成对出现

第三步:在resource路径下新建文件/META-INF/spring.schemas文件,指定custom.xsd 指向的配置文件

http\://com.david.study.spring/schema/custom/custom.xsd = com/david/study/spring/custom/namespace/custom.xsd

第三步:在src目录中创建一个CustomerNamespaceHandler 类

public class CustomNamespaceHandler extends NamespaceHandlerSupport {
    @Override
    public void init() {
        registerBeanDefinitionParser("custom",new CustomBeanDefinitionParse());
    }

}

这个地方主要是注册我们自己的BeanDefinitionParse,注意key custom要跟自己的命名空间一致

第四步:实现CustomBeanDefinitionParse,解析自己定义的xsd文件的标签

public class CustomBeanDefinitionParse extends AbstractSingleBeanDefinitionParser {

    static final String  CUSTOM_ID_ATTRIBUTE = "id";
    static final String  CUSTOM_NAME_ATTRIBUTE = "name";
    static final String  CUSTOM_AGE_ATTRIBUTE = "age";
    static final String  CUSTOM_SEX_ATTRIBUTE = "sex";
    static final String  CUSTOM_CLASS_ATTRIBUTE = "class";

    @Override
    protected String getBeanClassName(Element element) {
        return element.getAttribute(CUSTOM_CLASS_ATTRIBUTE);
    }

    @Override
    protected void doParse(Element element, BeanDefinitionBuilder builder) {
        builder.addPropertyValue(CUSTOM_ID_ATTRIBUTE,element.getAttribute(CUSTOM_ID_ATTRIBUTE));
        builder.addPropertyValue(CUSTOM_AGE_ATTRIBUTE,element.getAttribute(CUSTOM_AGE_ATTRIBUTE));
        builder.addPropertyValue(CUSTOM_NAME_ATTRIBUTE,element.getAttribute(CUSTOM_NAME_ATTRIBUTE));
        builder.addPropertyValue(CUSTOM_SEX_ATTRIBUTE,element.getAttribute(CUSTOM_SEX_ATTRIBUTE));
    }
}

第五步:在resource/META-INF下创建文件spring.handlers

标注当前的命名空间的解析器:

http\://com.david.study.spring/schema/custom =com.david.study.spring.custom.namespace.CustomNamespaceHandler

第六步:在resource/META-INF下创建beans.xml文件



    

第七步:写一个Demo

public class SpringXmlNamespaceDemo {
    public static void main(String[] args) {
        DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory);
        xmlBeanDefinitionReader.loadBeanDefinitions("/META-INF/beans.xml");

        Map map = defaultListableBeanFactory.getBeansOfType(Custom.class);

        map.entrySet().forEach(entry->{
            System.out.printf("name: %s \n",entry.getKey());
            System.out.printf("value: %s \n",entry.getValue());
        });
    }
}

启动测试:

输出的就是当前我们配置的属性.

上面就是自定义命名空间的简单实现,dubbo的早起功能就是基于次原理实现的。不过比这个例子复杂太多

你可能感兴趣的:(spring,xml,自定义命名空间)