在Spring中使用Elastic-Job的示例如下
1<!--配置作业注册中心 --> 2<reg:zookeeper id="regCenter" server-lists="${gis.dubbo.registry.address}" 3 namespace="example-job" base-sleep-time-milliseconds="${elasticJob.zkBaseSleepTimeMilliseconds}" 4 max-sleep-time-milliseconds="${elasticJob.zkMaxSleepTimeMilliseconds}" 5 max-retries="${elasticJob.zkMaxRetries}" />
本文将通过<reg:zookeeper/>来讲解如何在Spring中自定义标签,其中更是包含了ElasticJob的启动入口。
Spring自定义标签的实现步骤主要包括:
- 在META-INF目录下定义xsd文件
- 定义NamespaceHandlerSupport实现类
- 注册BeanDefinitionParser
- 将自定义的NameSpace、xsd文件纳入Spring的管理范围内
下面将详细介绍各个步骤的实现细节。
1、在META-INF目录下定义xsd文件
Elastic-Job reg.xsd文件定义如下
1<?xml version="1.0" encoding="UTF-8"?> 2<xsd:schema xmlns="http://www.dangdang.com/schema/ddframe/reg" 3 xmlns:xsd="http://www.w3.org/2001/XMLSchema" 4 xmlns:beans="http://www.springframework.org/schema/beans" 5 targetNamespace="http://www.dangdang.com/schema/ddframe/reg" 6 elementFormDefault="qualified" 7 attributeFormDefault="unqualified"> 8 <xsd:import namespace="http://www.springframework.org/schema/beans"/> 9 10 <xsd:element name="zookeeper"> 11 <xsd:complexType> 12 <xsd:complexContent> 13 <xsd:extension base="beans:identifiedType"> 14 <xsd:attribute name="server-lists" type="xsd:string" use="required" /> 15 <xsd:attribute name="namespace" type="xsd:string" use="required" /> 16 <xsd:attribute name="base-sleep-time-milliseconds" type="xsd:string" /> 17 <xsd:attribute name="max-sleep-time-milliseconds" type="xsd:string" /> 18 <xsd:attribute name="max-retries" type="xsd:string" /> 19 <xsd:attribute name="session-timeout-milliseconds" type="xsd:string" /> 20 <xsd:attribute name="connection-timeout-milliseconds" type="xsd:string" /> 21 <xsd:attribute name="digest" type="xsd:string" /> 22 </xsd:extension> 23 </xsd:complexContent> 24 </xsd:complexType> 25 </xsd:element> 26</xsd:schema>
下面对文档中的标签进行详细阐述。
xsd:schema元素详解
- xmlns="http://www.dangdang.com/schema/ddframe/reg"
定义默认命名空间。如果元素没有前缀,则元素的命名空间为xmlns定义的命名空间。 - xmlns:xsd="http://www.w3.org/2001/XMLSchema"
引入xsd命名空间,该命名空间的URL为http://www.w3.org/2001/XMLSchema,元素前缀为xsd。 - xmlns:beans="http://www.springframework.org/schema/beans"
引入Spring beans命名空间。xmln-s:xx=""表示引入已存在的命名空间。 - targetNamespace="http://www.dangdang.com/schema/ddframe/reg"
定义该命名空间所对应的url,在xml文件中如果要使用,其xsi:schema-Location定义reg.xsd路径时必须以该值为键,例如应用程序中定义ela-sticjob的xml文件如下:
- elementFormDefault="qualified"
指定该xsd所对应的实例xml文件,引用该文件中定义的元素必须被命名空间所限定。例如在reg.xsd中定义了zookeeper这个元素,那么在spring-elastic-job.xml(xml文档实例)中使用该元素来定义时,必须这样写
<reg:zookeeper id="regCenter"/>
- attributeFormDefault
指定该xsd所对应的示例xml文件,引用该文件中定义的元素属性是否需要被限定,unqualified表示不需要被限定。如果设置为qualified:
则错误写法:
1<reg:zookeeper id="regCenter" server-lists="" …/>
其正确写法:
1<reg:zookeeper id="regCenter" reg:server-lists="" …/>
xsd:import
导入其他命名空间,<xsd:import name-space="http://www.springframework.org/schema/beans"/>表示导入spirng bea-ns命名空间。如果目标命名空间定义文件中没有指定targetNamespace,则需要使用include导入其他命令空间,例如:<import namespace="tnsB" schema-Lcation="B.xsd">
xsd:element
<xsd:element name="zookeeper">:定义zookeeper元素,xml文件中可以使用<reg:zookeeper/>。
xsd:complexType
<xsd:complexType>,zookeeper元素的类型为复杂类型。
xsd:extension
<xsd:extension base="beans:identifiedType">
继承beans命名空间identifiedType的属性(id 定义)。
2、定义NamespaceHandlerSupport实现类。
继承NamespaceHandlerSupport,重写init方法。
1public final class RegNamespaceHandler extends NamespaceHandlerSupport { 2 3 @Override 4 public void init() { 5 registerBeanDefinitionParser("zookeeper", new ZookeeperBeanDefinitionParser()); 6 } 7}
3、注册BeanDefinitionParser
注册BeanDefinitionParser解析标签,并初始化实例。
ZookeeperBeanDefinitionParser源码:
1public final class ZookeeperBeanDefinitionParser extends AbstractBeanDefinitionParser { 2 @Override 3 protected AbstractBeanDefinition parseInternal(final Element element, final ParserContext parserContext) { 4 BeanDefinitionBuilder result = BeanDefinitionBuilder.rootBeanDefinition(ZookeeperRegistryCenter.class);// @1 5 result.addConstructorArgValue(buildZookeeperConfigurationBeanDefinition(element)); // @2 6 result.setInitMethodName("init"); // @3 7 return result.getBeanDefinition(); // @4 8 } 9 // ....省略部分代码 10}
代码@1:构建器模式,表明标签对应的实体Bean对象为ZookeeperRegistryCe-nter,zk注册中心实现类。
代码@2:最终创建ZookeeperRegistr-yCenter,其属性通过构造方法注入。
代码@3:设置initMethod,相当于配置文件的init-method属性,表明在创建实例时将调用该方法进行初始化。
代码@4:返回AbstractBeanDefinition对象,方便Spring针对该配置创建实例。
接下来重点分析一下buildZookeeperCo-nfigurationBeanDefinition的实现细节:
1private AbstractBeanDefinition buildZookeeperConfigurationBeanDefinition(final Element element) { 2 BeanDefinitionBuilder configuration = BeanDefinitionBuilder.rootBeanDefinition(ZookeeperConfiguration.class); 3 configuration.addConstructorArgValue(element.getAttribute("server-lists")); 4 configuration.addConstructorArgValue(element.getAttribute("namespace")); 5 addPropertyValueIfNotEmpty("base-sleep-time-milliseconds", "baseSleepTimeMilliseconds", element, configuration); 6 addPropertyValueIfNotEmpty("max-sleep-time-milliseconds", "maxSleepTimeMilliseconds", element, configuration); 7 addPropertyValueIfNotEmpty("max-retries", "maxRetries", element, configuration); 8 addPropertyValueIfNotEmpty("session-timeout-milliseconds", "sessionTimeoutMilliseconds", element, configuration); 9 addPropertyValueIfNotEmpty("connection-timeout-milliseconds", "connectionTimeoutMilliseconds", element, configuration); 10 addPropertyValueIfNotEmpty("digest", "digest", element, configuration); 11 return configuration.getBeanDefinition(); 12 }
上述代码比较简单明了,主要是根据<r-eg:zookeeper/>标签,获取element的s-erver-lists、namespace属性,使用Zoo-keeperConfiguration构造方式初始化Zo-keeperConfiguration属性,然后解析其他非空属性并使用set方法注入到Zook-eeperConfiguration实例中。
4、将自定义的NameSpace、xsd文件纳入Spring的管理范围内。
在META-INF目录下创建spring.handle-rs、spring.schemas文件,其内容分别是:
- spring.handlers
1http://www.dangdang.com/schema/ddframe/reg=io.elasticjob.lite.spring.reg.handler.RegNamespaceHandler
其定义格式:xsd文件中定义的targetN-amespace=自定义namespace实现类。
- spring.schemas:
1http\://www.dangdang.com/schema/ddframe/reg/reg.xsd=META-INF/namespace/reg.xsd
其定义格式:xsd文件uri = xsd文件目录。
xml中xsi:schemaLocation取的就是该文件中的内容,其示例如下:
1xsi:schemaLocation="http\://www.dangdang.com/schema/ddframe/reg/reg.xsd=META-INF/namespace/reg.xsd",
上述简单的通过elasticjob命名空间的引入示例展示如何在Spring自定义标签,也引出了Elasticjob的启动入口,下文将详细介绍ElasticJob Spring方式的启动流程。