spring 定义自己的标签 学习

自己的自定义配置文件spring 在,有时你想要做一些配置信息的数据结构。基于扩展生意做。

首先:

在项目META-INF文件夹中创建两个文件spring.handlers,和spring.shcemas

Spring.handlers在类org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver中已经写死了要取mapping的handlerMappingsLocation的路径

public static finalString DEFAULT_HANDLER_MAPPINGS_LOCATION ="META-INF/spring.handlers";

Spring.Schemas 在org.springframework.beans.factory.xml.PluggableSchemaResolver这个类中

相同写死了位置

public static finalString DEFAULT_SCHEMA_MAPPINGS_LOCATION = "META-INF/spring.schemas";

初始化的时候第一次调用的时候会调用

PropertiesLoaderUtils.loadAllProperties(this.schemaMappingsLocation,this.classLoader)

把全部的文件名称包括的取出来放入map中。


spring.handlers内容:

http://www.ruishenh.com/custom/mytest=com.ruishenh.spring.config.MyNamespaceHandler


spring.schemas内容:

http://www.ruishenh.com/custom/mytest/myTest.xsd=customTag/myTest.xsd


customTag/myTest.xsd文件:

 

<?xml version="1.0"encoding="UTF-8"?>
<xsd:schema xmlns="http://www.ruishenh.com/custom/myTest"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.ruishenh.com/custom/mytest"
    elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xsd:element name="executor">
        <xsd:complexType>
            <xsd:attribute name="name" type="xsd:string">
            </xsd:attribute>
            <xsd:attribute name="delay" type="xsd:int">
            </xsd:attribute>
            <xsd:attribute name="interval" type="xsd:int"use="required">
            </xsd:attribute>
            <xsd:attribute name="address" type="xsd:string">
            </xsd:attribute>
            <xsd:attribute name="entity" type="xsd:string">
            </xsd:attribute>
        </xsd:complexType>
    </xsd:element>
    <xsd:element name="entity">
        <xsd:complexType>
            <xsd:attribute name="name" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[ bean Name ]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <xsd:attribute name="splitBy" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation xml:lang="zh"><![CDATA[ sqoop切割字段 ]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <xsd:attribute name="sql" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation xml:lang="zh"><![CDATA[数据库操作sql]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
            <xsd:attribute name="dbTypeID">
                <xsd:annotation>
                    <xsd:documentation xml:lang="zh">
                    <![CDATA[ 指定数据库类型 假设类型不存在就推断dbTypeName属性,1是mysql。2是oracle,3是sqlserver    ]]>
                    </xsd:documentation>
                </xsd:annotation>
                <xsd:simpleType>
                    <xsd:restriction base="xsd:int">
                        <xsd:enumeration value="1" />
                        <xsd:enumeration value="2" />
                        <xsd:enumeration value="3" />
                    </xsd:restriction>
                </xsd:simpleType>
            </xsd:attribute>
            <xsd:attribute name="dbTypeName">
                <xsd:annotation>
                    <xsd:documentation xml:lang="zh"><![CDATA[ 指定数据库指定名称  假设  dbTypeID 不存在就取当前值 ]]></xsd:documentation>
                </xsd:annotation>
                <xsd:simpleType>
                    <xsd:restriction base="xsd:string">
                        <xsd:enumeration value="mysql" />
                        <xsd:enumeration value="oracle" />
                        <xsd:enumeration value="sqlserver" />
                    </xsd:restriction>
                </xsd:simpleType>
            </xsd:attribute>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

spring/myTest.xml文件:

<?xml version="1.0"encoding="UTF-8"?

> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:mi="http://www.ruishenh.com/custom/mytest" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.ruishenh.com/custom/mytesthttp://www.ruishenh.com/custom/mytest/myTest.xsd"> <mi:entity dbTypeID="1" dbTypeName="mysql"splitBy="id" sql="1" name="mye" /> <mi:executor interval="5000" address="127.0.0.1"delay="2000" name="myexecutor" entity="mye" /> </beans>



com.ruishenh.spring.config.MyNamespaceHandler  命名空间处理类:

 

package com.ruishenh.spring.config;
 
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
 
public class MyNamespaceHandler extends NamespaceHandlerSupport{
 
    @Override
    public void init() {
        registerBeanDefinitionParser("executor",newMyBeanDefinitionParser(MyExecutor.class));
        registerBeanDefinitionParser("entity",newMyBeanDefinitionParser(MyEntity.class));
    }
 
}

这个类主要是在DefaultNamespaceHandlerResolver这个类中getHandlerMappings()取到了全部的META-INF/spring.handlers的文件内容存入map,然后依据当前的命名空间找到相应的NamespaceHandler,然后反射出对象调用init()

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");
                }
                NamespaceHandlernamespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
                namespaceHandler.init();
 
 


com.ruishenh.spring.config.MyBeanDefinitionParser解析类:

 

packagecom.ruishenh.spring.config;
 
importorg.springframework.beans.factory.config.BeanDefinition;
importorg.springframework.beans.factory.config.RuntimeBeanReference;
importorg.springframework.beans.factory.support.RootBeanDefinition;
importorg.springframework.beans.factory.xml.BeanDefinitionParser;
importorg.springframework.beans.factory.xml.ParserContext;
importorg.w3c.dom.Element;
importorg.w3c.dom.NamedNodeMap;
importorg.w3c.dom.Node;
 
public classMyBeanDefinitionParser implements BeanDefinitionParser {
 
         private Class<?> clssze;
 
         publicMyBeanDefinitionParser(Class<?

> cls) { this.clssze = cls; } @Override public BeanDefinition parse(Elementelement, ParserContext parserContext) { RootBeanDefinitionbeanDefinition = new RootBeanDefinition(); beanDefinition.setBeanClass(clssze); String id = null; id =element.getAttribute("name"); if (id == null) { if (clssze ==MyExecutor.class) { id = "test_myExecutor"; } else if (clssze ==MyEntity.class) { id ="test_myentity"; } else { throw newIllegalStateException("MyBeanDefinitionParser.parse,未知的业务逻辑处理:class:" +element.getAttribute("class")); } } int counter = 2; while(parserContext.getRegistry().containsBeanDefinition(id)) { id = id +(counter++); } if (id != null &&id.length() > 0) { if(parserContext.getRegistry().containsBeanDefinition(id)) { throw newIllegalStateException("Duplicate spring bean id " + id); } parserContext.getRegistry().registerBeanDefinition(id,beanDefinition); } NamedNodeMap nnm =element.getAttributes(); for (int i = 0; i <nnm.getLength(); i++) { Node node =nnm.item(i); String key =node.getLocalName(); String value =node.getNodeValue(); if(key.equals("entity")) { if(parserContext.getRegistry().containsBeanDefinition(value)) { beanDefinition.getPropertyValues().add(key,parserContext.getRegistry().getBeanDefinition(value)); } else { beanDefinition.getPropertyValues().add(key,new RuntimeBeanReference(value)); } } else { beanDefinition.getPropertyValues().add(key,value); } } return beanDefinition; } }


这个类会在

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(Elementroot, BeanDefinitionParserDelegate delegate)这种方法中入口运行

然后到org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse(Elementelement, ParserContext parserContext);

最后找到相应的BeanDefinitionParser运行parse方法。至于放入BeanDefinitionParser的入口就在自己定义的NamespaceHandler中init()方法中。

com/ruishenh/spring/config/MyEntity.java实体类:

 

package com.ruishenh.spring.config;
 
import com.ruishenh.model.BaseModel;
 
public classMyEntity extendsBaseModel{
 
    private int dbTypeID;
 
    private String dbTypeName;
 
    private String splitBy;
 
    private String sql;
 
    private String name;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getSplitBy() {
        return splitBy;
    }
 
    public void setSplitBy(StringsplitBy) {
        this.splitBy = splitBy;
    }
 
    public String getSql() {
        return sql;
    }
 
    public void setSql(String sql) {
        this.sql = sql;
    }
 
    public int getDbTypeID() {
        return dbTypeID;
    }
 
    public void setDbTypeID(int dbTypeID) {
        this.dbTypeID = dbTypeID;
    }
 
    public String getDbTypeName(){
        return dbTypeName;
    }
 
    public void setDbTypeName(StringdbTypeName) {
        this.dbTypeName = dbTypeName;
    }
 
}
 

com/ruishenh/spring/config/MyExecutor.java实体类:

 

package com.ruishenh.spring.config;
 
import com.ruishenh.model.BaseModel;
 
public classMyExecutor  extends BaseModel{
 
    private String name;
 
    private int delay;
 
    private int interval;
 
    private String address;
 
    private MyEntity entity;
 
    public MyEntity getEntity() {
        return entity;
    }
 
    public void setEntity(MyEntity entity) {
        this.entity = entity;
    }
 
    public int getDelay() {
        return delay;
    }
 
    public void setDelay(int delay) {
        this.delay = delay;
    }
 
    public int getInterval() {
        return interval;
    }
 
    public void setInterval(int interval) {
        this.interval = interval;
    }
 
    public String getAddress() {
        return address;
    }
 
    public void setAddress(Stringaddress) {
        this.address = address;
    }
 
   
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
}

測试类:

package com.ruishenh.spring.test;
 
import org.springframework.context.support.FileSystemXmlApplicationContext;
 
import com.ruishenh.spring.config.MyEntity;
import com.ruishenh.spring.config.MyExecutor;
 
public classTest {
    public static void main(String[] args) {
        Stringconf = "classpath:spring/myTest.xml";
        FileSystemXmlApplicationContextac = newFileSystemXmlApplicationContext(conf);
        MyExecutorme = ac.getBean(MyExecutor.class);
        System.out.println(me.toString());
        MyEntity mye = ac.getBean(MyEntity.class);
        System.out.println(mye.toString());
    }
}
 


执行结果:

MyExecutor[name=myexecutor,delay=2000,interval=5000,address=127.0.0.1,entity=MyEntity[dbTypeID=1,dbTypeName=mysql,splitBy=id,sql=1,name=mye]]

MyEntity[dbTypeID=1,dbTypeName=mysql,splitBy=id,sql=1,name=mye]

版权声明:本文博客原创文章。博客,未经同意,不得转载。

原文地址:https://www.cnblogs.com/lcchuguo/p/4635448.html