框架 Dubbo 扩展Spring Schema介绍

186 阅读1分钟

问题Dubbo如果扩展Spring Schema?

从一个例子开始,写一个类让Spring解析 对比Dubbo
  • DubboNamespaceHandler extends NamespaceHandlerSupport
  • MyNamespaceHandler extends NamespaceHandlerSupport
```Java
public class MyNamespaceHandler extends NamespaceHandlerSupport {
    public void init() {
        registerBeanDefinitionParser("people",new PeopleBeanDefinitionParser());
    }
}
```
  • 这里需要一个解析器 new PeopleBeanDefinitionParser()
  • registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
```Java
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.isNotBlank(name)){
            builder.addPropertyValue("name",name);
        }
        if (StringUtils.isNotBlank(age)){
            builder.addPropertyValue("age",age);
        }
        if (StringUtils.isNotBlank(id)){
            builder.addPropertyValue("id",id);
        }

    }
}
```
  • 从下图的分析中我们还了解到 我们还需要一个xsd配置和一个handlers还有一个schemas
  • 模仿着搞出来
  • 1.xsd 用于配置解析的元素
  • 2.handlers 用于指定解析元素的类对应上面写的MyNamespaceHandler it.caoxin/schema/peop…
  • 3.schemas 用于指定解析元素的xsd文件 it.caoxin/schema/peop…

- 4.标准类用于接收解析出来的xml
```Java
public class People {
    private String id;
    private String name;
    private Integer age;
    // 省略getter setter
}
```
  • 5.执行如下代码
```Java
// 获取配置文件
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获取配置文件中自定义schema的bean
        // 

        // 定义了这个schema后我们需要找到对应的验证文件 和 bean解析类
        //  http://it.caoxin/schema/people bean解析实体类
        // http://it.caoxin/schema/people.xsd 提供需要验证的文件
        People p= (People) ctx.getBean("cutesource");
        System.out.println(p.getId());
        System.out.println(p.getName());
        System.out.println(p.getAge());

```
  • 6.程序运行结果

  • cutesource

  • caoxinxin

  • 15

  • Spring在哪里解析这个类的?调用链

  • org.springframework.context.support.AbstractApplicationContext#refresh()

  • ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

  • org.springframework.context.support.AbstractApplicationContext#refreshBeanFactory

  • org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.support.DefaultListableBeanFactory)

  • org.springframework.beans.factory.xml.XmlBeanDefinitionReader#doLoadBeanDefinitions

  • org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitions

  • org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseCustomElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)

  • 这里的做法是通过元素获取NamespaceURI,再通过取NamespaceURI获取对应的NameSpaceHandler,最后调用NameSpaceHandler.parse()进行解析,返回BeanDefinition

  • 思想:

  • 通过spring.handler配置自定义元素解析器。

  • 通过spring.schemas对需要解析的内容进行定义。

  • 高扩展性,解耦的体现。