在Webx中添加扩展点的示例

1. 背景

在前一篇文章中,我们使用SpringExt添加了一个Webx的回显服务扩展(详见“使用SpringExt扩展Webx的示例”),这个服务把传入的字符串原样返回,并加上一个可自定义的标题。很自然的,我们就会进一步想到能否自己给Webx添加一个新的扩展点,本文实现了一个示例,在回显服务上添加一个字符串的修饰(Decorate)扩展点,让服务在返回之前能对字符串稍加修饰,比如把字母全部变成大写的,或是在字符串的最末尾添加一个笑脸。

1.1. 相关概念

主要涉及到Webx中的扩展点(Configuration Point)和扩展(Contriubtion),具体内容参见Webx的文档http://openwebx.org/docs/springext.html。

1.2. 示例代码

代码托管在Google Code上http://joshuazhan.googlecode.com/svn/trunk/webx/springext/configuration-points.echo/,用SVN检出以及用Maven构建项目。使用说明同前篇3.1节。

2. 示例详解

2.1. Decorator接口

在Webx中添加扩展点的示例_第1张图片

回显服务实现类EchoServiceImpl比原先多了一个decorator属性,对应的是一个修饰器对象(可为空)。修饰器的接口为Decorator,目前一共有提供了3种实现,LowerCaseDecorator专门把传入的消息变成小写的,UpperCaseDecorator与LowerCaseDecorator相反,而SmileDecorator则是在消息的最末端添加一个笑脸符号。

2.2. EchoServiceDefinitionParser

在Webx中添加扩展点的示例_第2张图片

在本例中,由于添加了Decorator扩展点,EchoService的配置解析器比原先的要复杂,所以单独成一个类EchoServiceDefinitionParser。EchoServiceDefinitionParser比原先多实现了ContributionAware接口,能够感知自己在Webx中对应的Contribution实例,EchoService本身即是对Service扩展点(Configuration Point)的扩展(Contribution)。Webx在初始化解析器时会通过setContribution方法将Contribution实例传给解析器。

通过Contribution对象,EchoServiceDefinitionParser获取到Decorator扩展点对应的ConfigurationPoint实例,这里使用了SpringExtUtil提供的getSiblingConfigurationPoint方法。

@Override
public void setContribution(Contribution contrib) {
	// 获取Decorator扩展点实例
	decoratorsConfigurationPoint = getSiblingConfigurationPoint(
			"services/echo-service/decorators", contrib);
}

在解析回显服务配置的过程中(见doParse方法),EchoServiceDefinitionParser调用parseDecorator方法完成Decorator配置的解析。

/**
 * 解析回显服务的消息修饰器配置,如果存在就生成对应的修饰器Bean定义
 */
private void parseDecorator(Element element, ParserContext parserContext,
		BeanDefinitionBuilder builder) {
	// 获取唯一的Decorator子元素
	Element decoratorElement = theOnlySubElement(element,
			ns(DECORATOR_NAMESPACE));
	if (null == decoratorElement) {
		return;
	}
	
	// 根据扩展点生成Decorator元素对应的BeanDefinition
	BeanDefinitionHolder decoratorBean = parseConfigurationPointBean(
			decoratorElement, decoratorsConfigurationPoint, parserContext, builder);
	// 作为一个内部Bean设置到Echo Service的BeanDefinition中
	builder.addPropertyValue("decorator", decoratorBean);
}

2.3. echo-service的Schema

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
	……
	<xsd:complexType name="EchoServiceType">
		<xsd:sequence>
			<xsd:element name="title" type="xsd:string" default="Echo" />
			<xsd:any namespace="http://www.alibaba.com/schema/services/echo-service/decorators" 
					minOccurs="0" />
		</xsd:sequence>
		……
	</xsd:complexType>

</xsd:schema>

回显服务的Schema与之前的不同之处在于XML配置里增加了一个可选的Decorator子元素,任何在Decorator Namespace(“http://www.alibaba.com/schema/services/echo-service/decorators”)下的元素都可以添加到配置中,此处使用到了Schema的any元素(对该元素的介绍可参看W3school“XSD <any> 元素”)。

2.4. Decorator扩展点

Decorator扩展点的定义在项目”META-INF/spring.configuration-points”文件中,内容如下。

services/echo-service/decorators=http://www.alibaba.com/schema/services/echo-service/decorators; defaultElement=decorator;

扩展点名称为“services/echo-service/decorators”,对应的Schema是“http://www.alibaba.com/schema/services/echo-service/decorators”,decorator为默认的元素。

在此我们给回显服务留下了两种扩展方式:第一种是自定义新的扩展元素、及其属性和子元素,示例代码中的UpperCaseDecorator和LowerCaseDecorator即是基于这种方式实现的;第二种方式则较为简单,直接使用默认的decorator元素,只要提供一个Decorator接口的实现类(示例中的SmileDecorator),然后像配置Spring Bean一样配置decorator元素即可。下面是对示例的说明。

2.4.1. 自定义扩展元素

这种方式可以实现较为复杂的需求,能自定义新的元素,并使用Schema来对配置内容和格式进行控制,甚至是添加新的扩展点。“使用SpringExt扩展Webx的示例”有对实现扩展的详细说明,而本文的回显服务则更侧重于说明如何添加一个新扩展点。UpperCaseDecorator和LowerCaseDecorator这两个扩展则是最简单的一种扩展实现,各自提供了一个元素,没有其他内容,Schema定义和实现类也较为简单,在此不多做解释。

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
	<xsd:element name="lowercase" />
</xsd:schema>
public class LowerCaseDecorator implements Decorator {

	@Override
	public String decorate(String message) {
		return message.toLowerCase();
	}

	/**
	 * <pre>
	 * 最简单的Decorator扩展实现,只继承了AbstractSingleBeanDefinitionParser并通过泛型参数传入类型定义
	 * 配置解析和Bean的生成都由父类完成
	 * </pre>
	 */
	public static class DefinitionParser extends
			AbstractSingleBeanDefinitionParser<LowerCaseDecorator> {
	}

}

2.4.2. 默认元素

在多数情况下,我们的扩展没有复杂的配置,也不需要留扩展点给他人扩展。这时为这些扩展编写的Schema定义和解析器是没有太大意义的,扩展点里定义的默认元素则能解决这个问题,以SmileDecorator为例来说明(见示例代码中的配置文件configuration2.xml)。

<echo-service xmlns="http://www.alibaba.com/schema/services">
	<title>Echo</title>
	<!-- 
		使用了默认元素的扩展,decorator元素兼容Spring Bean的配置
	 -->
	<es-decorators:decorator class="me.joshua.webx.springext.configurationpoints.echo.decorator.SmileDecorator" />
</echo-service>

在上面的回显服务配置中,修饰器是通过默认元素decorator添加的,其中decorator的class属性里指明了SmileDecorator的完整类名。在此完全可以把decorator视为Spring中的“bean”元素,事实上SpringExt中的默认元素对Spring原生的bean元素做了兼容,你甚至可以用ref属性来引用另一个已经定义好的Bean(见示例代码中的配置文件configuration3.xml),或是通过constructor-arg和property子元素来设置构造函数参数和属性值。

2.5. 示例代码的运行

示例的代码可以直接通过me.joshua.webx.springext.configurationpoints.echo.Launcher来运行,里面包括了几种不同的Decorator扩展的配置和使用示例。

3. 其他

3.1. 参考

Webx文档http://openwebx.org/docs/index.html

3.2. 相关文章

使用SpringExt扩展Webx的示例http://my.oschina.net/joshuazhan/blog/81654

你可能感兴趣的:(configuration,示例,扩展点,webx,point,SpringExt)