spring模仿dubbo自定义schema解析并注入容器

Posted 醉酒的小男人

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring模仿dubbo自定义schema解析并注入容器相关的知识,希望对你有一定的参考价值。

dubbo里边有很多如provider、consumer、registry的配置都是通过spring自定义Schema来实现的,模仿写一个demo来加深记忆。

步骤如下

  • 编写定义java bean
  • 编写xsd配置文件
  • 编写spring.handlersspring.schemas
  • 编写myschema.xml
  • 编写NamespaceHandler和BeanDefinitionParser

代码案例

本地代码结构

定义java bean

package myschema.model;

public class User {
    private String id;
    private String name;
    private String sex;
    private int 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 String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

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

编写resources/META-INF/user.xsd文件

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<xsd:schema xmlns="http://www.orchome.com/eric-lin/schema/user"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:beans="http://www.springframework.org/schema/beans"
            targetNamespace="http://www.orchome.com/eric-lin/schema/user">

    <xsd:import namespace="http://www.springframework.org/schema/beans"/>

    <xsd:element name="user">
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="beans:identifiedType">
                    <xsd:attribute name="name" type="xsd:string">
                        <xsd:annotation>
                            <xsd:documentation>姓名</xsd:documentation>
                        </xsd:annotation>
                    </xsd:attribute>

                    <xsd:attribute name="sex" type="xsd:string">
                        <xsd:annotation>
                            <xsd:documentation>性别</xsd:documentation>
                        </xsd:annotation>
                    </xsd:attribute>

                    <xsd:attribute name="age" type="xsd:int">
                        <xsd:annotation>
                            <xsd:documentation>年龄</xsd:documentation>
                        </xsd:annotation>
                    </xsd:attribute>
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

resources/META-INF/spring.schemas 文件内容

http\\://www.orchome.com/eric-lin/schema/user=myschema.UserNamespaceHandler

resources/META-INF/spring.handlers 文件内容

http\\://www.orchome.com/eric-lin/schema/user/user.xsd=META-INF/user.xsd

myschema.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:test="http://www.orchome.com/eric-lin/schema/user"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://www.orchome.com/eric-lin/schema/user
        http://www.orchome.com/eric-lin/schema/user/user.xsd">
    <test:user id="test1" name="张三" sex="男" age="30" />
</beans>

NamespaceHandler

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

public class UserNamespaceHandler extends NamespaceHandlerSupport {
    @Override
    public void init() {
       //registerBeanDefinitionParser("user",new DubboBeanDefinitionParser());
        registerBeanDefinitionParser("user",new UserBeanDefinitionParser());
    }
}

继承AbstractSingleBeanDefinitionParser 

package myschema;
import myschema.model.User;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.w3c.dom.Element;

public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

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

    @Override
    protected void doParse(Element element, BeanDefinitionBuilder bean) {
        String id = element.getAttribute("id");
        String name = element.getAttribute("name");
        String sex = element.getAttribute("sex");
        int age = Integer.parseInt(element.getAttribute("age"));
        bean.addPropertyValue("id",id);
        bean.addPropertyValue("name", name);

        System.out.println("==========================第一种方式继承AbstractSingleBeanDefinitionParser=========================================");

        bean.addPropertyValue("sex", sex);
        bean.addPropertyValue("age", age);
    }
}

另外一种方式也可以实现BeanDefinitionParser

package myschema;
import myschema.model.User;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;

public class DubboBeanDefinitionParser implements BeanDefinitionParser {

    @Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        RootBeanDefinition beanDefinition = new RootBeanDefinition();
        beanDefinition.setBeanClass(User.class);
        beanDefinition.setLazyInit(false);
        String id = element.getAttribute("id");
        String name = element.getAttribute("name");
        String sex = element.getAttribute("sex");
        int age = Integer.parseInt(element.getAttribute("age"));

        System.out.println("==========================第二种方式实现BeanDefinitionParser=========================================");

        beanDefinition.getPropertyValues().addPropertyValue("id", id);
        beanDefinition.getPropertyValues().addPropertyValue("name", name);
        beanDefinition.getPropertyValues().addPropertyValue("sex", sex);
        beanDefinition.getPropertyValues().addPropertyValue("age", age);
        parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);
        return beanDefinition;
    }
}

测试类

package myschema;
import myschema.model.User;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestSchema {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:myschema.xml");
        User test1 = (User) context.getBean("test1");
        System.out.println(test1.getId());
        System.out.println(test1.getName());
        System.out.println(test1.getSex());
        System.out.println(test1.getAge());
    }
}

结果

以上是关于spring模仿dubbo自定义schema解析并注入容器的主要内容,如果未能解决你的问题,请参考以下文章

Dubbbo spring配置方式解析

Dubbbo spring配置方式解析

dubbo源码—dubbo自定义spring xml标签

Dubbo中对Spring配置标签扩展

Dubbo面试八股文—1

Dubbo源码分析系列-扩展机制的实现