WebX对Spring的扩展
WebX主要对Spring解析自定义的命名空间Element元素的逻辑上做了扩展。其中最重要的实现类ConfigurationPointImpl继承自NamespaceHandlerSupport,即实现了NamespaceHandler接口。
在Spring中,通过META-INF/spring.handlers文件找到namespaceURI到NamespaceHandler的map,而WebX中的springext则自定义了XmlBeanDefinitionReader中的EntityResolver(SchemaEntityResolver)和NamespaceHandlerResolver(ConfigurationPointNamespaceHandlerResolver)实例。
其中在SchemaEntityResolver中,先从传入的SpringExtSchemaSet中查找传入的namespaceURI对应的,如果能存在,则使用找到的Schema实例构建InputSource,否则使用Spring默认提供的PluggableEntityResolver。
在ConfigurationPointNamespaceHandlerResolver中,它使用SpringExtSchemaSet中获取的ConfigurationPoints查找传入的namespaceURI对应的ConfigurationPoint,如果有找到则使用该ConfigurationPoint中的NamespaceHander(一般就是它自己),否则使用Spring默认提供的DefaultNamespaceHandlerResolver,即从META-INF/spring.handlers读取映射关系。所以SpringExtSchemaSet是WebX中的springext最关键实现,也是它所谓的扩展点所在,并且它和Spring是完全兼容的。
进一步的,SpringExtSchemaSet的关键实现是如何从当前classpath中找到所有namespaceURI到Schema的映射,以及如何找到每个自定义的Element tag名到自定义的BeanDefinitionParser的映射。SpringExtSchemaSet通过两个类来实现这些功能:ConfigurationPoints(ConfigurationPointsImpl)和SpringPluggableSchemas。
其中ConfigurationPointsImpl查找classpath内所有的META-INF/spring.configuration-points文件,根据文件的内容创建ConfigurationPoint,该文件为key=value的properties文件,其中key为所有子自定义命名空间的xsd文件夹路径,value格式为:
namespaceURI; defaultElement=<elment-tag>; nsPrefix=<prefix>
如: services/pipeline/valves=http://www.alibaba.com/schema/services/pipeline/valves; defaultElement=valve; nsPrefix=pl-valves
因为ConfigurationPoint也是一个NamespaceHandler(继承自NamespaceHandlerSupport),因而它需要实现init()方法,并在init()方法中注册每个自定义Element tag到BeanDefinitionParser的映射。ConfigurationPoint支持三种类型的Contribution:.bean-definition-parsers、.bean-definition-decorators、*.bean-definition-decorators-for-attribute,分别对应META-INF目录下的services-pipeline-valves.bean-definition-parsers、services-pipeline-valves.bean-definition-decorators、services-pipeline-valves.bean-definition-decorators-for-attribute,其中services-pipeline-valves是spring.configuration-points文件中的key('/'替换成'-')。这些文件中的key为XML文件中的自定义的Element tag,value为BeanDefinitionParser或BeanDefinitionDecorator。每个文件抽象成一个Contribution实例,在Contribution中查找创建对应的Schema类(xsd文件),查找路径为configurationPointName/contributionName。最后注册defaultElement(如:valve)到DefaultElementDefinitionParser的映射,它可以解析一个正常的Bean定义(除了Element tag不是bean),或者一个Bean引用,如:<valve ref="myValve" />
最后SpringPluggableSchemas则从META-INF/spring.schemas读取namespaceURI到xsd文件路径的映射,并转换成本地xsd文件,以及META-INF/spring.handlers中读取所有自定义的namespace。从META-INF/spring.tooling文件中读取默认的namespace prefix。