dubbo学习-spring schema扩展

dubbo对spring的标签的扩展

<dubbo:application name="${dubbo.application.name}" owner="whx" organization="whx-inc"/>
<dubbo:registry protocol="zookeeper"
                address="${dubbo.registry.address}"
                group="${dubbo.registry.group}"
                file="${dubbo.registry.file}"/>

<dubbo:annotation package="com.whx"/>

<dubbo:consumer check="false" retries="0"/>

<dubbo:provider threads="600" threadpool="fixed" retries="0" loadbalance="roundrobin" accesslog="true"/>

<dubbo:protocol name="dubbo" port="${dubbo.protocol.dubbo.port}" charset="utf-8"/>

<dubbo:protocol name="hessian" port="${jetty.port}" server="jetty" accesslog="true"/>
<dubbo:protocol name="rest" port="${dubbo.protocol.rest.port}"
   keepalive="true" server="netty" 
   extension="com.whx.common.rest.FastJsonProvider,com.whx.common.rest.JsonExceptionMapper" />

<context:property-placeholder
        ignore-resource-not-found="false"
        location="classpath*:application.properties,classpath*:redis.properties,classpath*:dubbo.properties,classpath*:kestrel.properties,classpath*:db.properties" />
<dubbo:monitor address="${dubbo.monitor.address}" />

这些注解其实都是对spring标签的扩展,由spring的api扩展出来,方便我们不去读取xml,直接通过标签的方式加载为bean对象

public class DubboNamespaceHandler extends NamespaceHandlerSupport {

static {
    Version.checkDuplicate(DubboNamespaceHandler.class);
}

public void init() {
    registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
    registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
    registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
    registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
    registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
    registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
    registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
    registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
    registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
    registerBeanDefinitionParser("annotation", new DubboBeanDefinitionParser(AnnotationBean.class, true));
}

}

spring schema扩展实现

1.编写Bean类,此为业务类
public class People {

    private String id;
    private String name;
    private Integer age;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "People{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
2.编写xsd文件 xsd文件中包含了Bean类的属性映射
<?xml version="1.0" encoding="UTF-8"?>
    <xsd:schema
        xmlns="http://whx4j8.github.io/people"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:beans="http://www.springframework.org/schema/beans"
        targetNamespace="http://whx4j8.github.io/people"
        elementFormDefault="qualified"
        attributeFormDefault="unqualified">

    <xsd:import namespace="http://www.springframework.org/schema/beans"/>
    <xsd:element name="people">
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="beans:identifiedType">
                    <xsd:attribute name="name" type="xsd:string"/>
                    <xsd:attribute name="age" type="xsd:int"/>
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>

</xsd:schema>

element name=”people” 代表people,spring会通过其内的配置项xsd:attribute在xml提示字段,类似xml提示

xmlns targetNamespace 代表对应的唯一命名空间

一般将xsd放到META-INF下

3.编写NamespaceHandler 和 spring.schemas 映射配置文件

registerBeanDefinitionParser(“people”, new PeopleBeanDefinitionParser());

当读取到people这个节点名时,使用PeopleBeanDefinitionParser类去解析,而不是仅仅将字段注入属性中。

public class MyNamespaceHandler extends NamespaceHandlerSupport {

    @Override
    public void init() {
        registerBeanDefinitionParser("people", new PeopleBeanDefinitionParser());
    }

}

PeopleBeanDefinitionParser通过反射将xml中配置的值注入到生成的bean对象中。

public class PeopleBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

    @Override
    protected Class<?> getBeanClass(Element element) {
        return People.class;
    }


    @Override
    protected void doParse(Element element, BeanDefinitionBuilder builder) {
        String name = element.getAttribute("name");
        String age = element.getAttribute("age");
        String id = element.getAttribute("id");

        if (!StringUtils.isEmpty(name)){
            builder.addPropertyValue("name",name);
        }

        if (!StringUtils.isEmpty(age)){
            builder.addPropertyValue("age",age);
        }

        if (!StringUtils.isEmpty(id)){
            builder.addPropertyValue("id",id);
        }

    }
}
4.spring.handlers 和 spring.schemas

现在xml规范有了,xml解析器也有了,Bean对象也有了。

spring.handlers文件

http\://whx4j8.github.io/people=com.whx.spring.MyNamespaceHandler
告诉spring当使用http\://whx4j8.github.io/people使用com.whx.spring.MyNamespaceHandler去配置解析

spring.schemas文件

http\://whx4j8.github.io/people.xsd=META-INF/people.xsd
告诉spring去加载那些xsd文件
5.application.xml
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:whx="http://whx4j8.github.io/people"
       xsi:schemaLocation="
                http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                http://whx4j8.github.io/people
                http://whx4j8.github.io/people.xsd">

    <whx:people id="people" name="whx" age="22"></whx:people>
</beans>

xmlns:whx=”http://whx4j8.github.io/people“ 为该schema命名为whx,在下面的xml直接使用whx即可

6.使用
public static void main(String[] args){

    ApplicationContext ctx = new ClassPathXmlApplicationContext("application.xml");
    People people = (People) ctx.getBean("people");
    System.out.println(people.toString());

}

输出People{id=’people’, name=’whx’, age=22}

参考

dubbo源码解析