解析配置
解析配置,是Dubbo服务启动的第一步,基于Spring配置结合的框架都是从这一步开始启动的(包括之前提到的Motan);
Dubbo官方文档中提到:
初始化过程的第一步是从解析服务开始的,基于 dubbo.jar 内的 META-INF/spring.handlers 配置,
Spring 在遇到 dubbo 名称空间时,会回调 DubboNamespaceHandler。所有 dubbo 的标签,都统一用 DubboBeanDefinitionParser 进行解析,基于一对一属性映射,将 XML 标签解析为 Bean 对象。
真正想了解一只青蛙,传统的解剖不是办法,更好的方式是构造一只青蛙
所以想要了解这个过程,最好的方式是实现一个这样的过。
试想,在使用Dubbo的时候,配置各种标签:dubbo:application、dubbo:protocol、dubbo:service 等等;这些配置最终是如何转化成Dubbo框架的对象的;本文将试着照虎画猫,实现这样的一个功能。
目标:不使用传统的<bean>配置,使用自己定义的标签和命名空间来创建一个自定义的对象
创建MAVEN项目
创建项目过程,此处略过,增加spring的依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.8.RELEASE</version>
</dependency>
创建目标对象
也就是我们需要通过xml配置,生成出什么类型的对象,此处略过;
创建XML约束文件xsd:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://www.irvingsun.cn/schema/foo"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.irvingsun.cn/schema/foo">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
<xsd:import namespace="http://www.springframework.org/schema/beans"/>
<xsd:import namespace="http://www.springframework.org/schema/tool"/>
<xsd:complexType name="abstractPerson">
<xsd:attribute name="id" type="xsd:string" use="required"/>
<xsd:attribute name="firstname" type="xsd:string" use="required" />
<xsd:attribute name="lastname" type="xsd:string" use="required" />
<xsd:attribute name="age" type="xsd:int" use="required" />
<xsd:attribute name="gender" type="xsd:string" use="required"/>
<xsd:attribute name="address" type="xsd:string" />
</xsd:complexType>
<xsd:element name="person" type="abstractPerson"/>
</xsd:schema>
这个约束文件表示,我们需要创建一个名为person
的标签,它有id、firstname、lastname、age等属性。该文件位于resources/META-INF/
目录下。
同时在改目录下创建spring.schemas文件,该文件将告知spring,约束文件映射的本地具体位置,如果找不到,它将访问这个http地址查找;
http://www.irvingsun.cn/schema/foo.xsd=META-INF/foo.xsd
编写XML配置
此时,我们就可以通过这个xsd文件约束来创建XML配置文件了:
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:foo="http://www.irvingsun.cn/schema/foo"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.irvingsun.cn/schema/foo http://www.irvingsun.cn/schema/foo.xsd">
<foo:person id = "idx" firstname="sun" lastname="way" age="1" gender="male" />
</beans>
我们配置了一个person标签,并且给属性赋值;
通过Spring自动解析
- 创建Namespace解析处理器
public class PersonNamespaceHandler extends NamespaceHandlerSupport{
public void init() {
registerBeanDefinitionParser("person", new FooBeanDefinitionParser(Person.class, true));
}
}
此处注册了一个BeanDefinition解析器,用来解析person标签:
public class FooBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
protected Class getBeanClass(Element element) {
return Person.class;
}
protected void doParse(Element element, BeanDefinitionBuilder bean) {
String firstName = element.getAttribute("firstname");
String lastName = element.getAttribute("lastname");
String age = element.getAttribute("age");
String id = element.getAttribute("id");
String address = element.getAttribute("address");
if(!StringUtils.isEmpty(firstName)){
bean.addPropertyValue("firstName",firstName);
}
if(!StringUtils.isEmpty(lastName)){
bean.addPropertyValue("lastName",lastName);
}
if(!StringUtils.isEmpty(id)){
bean.addPropertyValue("id",id);
}
if(!StringUtils.isEmpty(address)){
bean.addPropertyValue("address",address);
}
if(!StringUtils.isEmpty(age)){
bean.addPropertyValue("age",Integer.parseInt(age));
}
}
}
从Element对象中加载出我们配置的值,并且返回BeanDefinition对象(父类中);
使用配置
和平时使用Spring的方式一样,通过加载XML配置文件:
public static void main( String[] args )
{
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"spring-config.xml"});
// context.start();
context.getBean(Person.class);
}
回到开始时提到的,和Spring集成的情况,Dubbo启动,根据这种方式来将我们配置的参数,实例化为框架中对应的对象。
-EOF-