浏览 14450 次
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2006-10-27
首先定义相关xsd文件,用于验证相应的行为: 主要增加了4个自定义元素和1个属性: <?xml version="1.0" encoding="UTF-8" standalone="no"?> <xsd:schema xmlns="http://www.springframework.org/schema/beans/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.springframework.org/schema/beans/test" elementFormDefault="qualified"> <xsd:element name="testBean"> <xsd:complexType> <xsd:attribute name="id" type="xsd:string" use="required" form="unqualified"/> <xsd:attribute name="name" type="xsd:string" use="required" form="unqualified"/> <xsd:attribute name="age" type="xsd:integer" use="required" form="unqualified"/> </xsd:complexType> </xsd:element> <xsd:element name="set"> <xsd:complexType> <xsd:attribute name="name" type="xsd:string" use="required" form="unqualified"/> <xsd:attribute name="age" type="xsd:integer" use="required" form="unqualified"/> </xsd:complexType> </xsd:element> <xsd:element name="debug"/> <xsd:element name="nop"/> <xsd:attribute name="object-name" type="xsd:string"/> </xsd:schema> 接着定义handler映射文件:customNamespace.properties http\://www.springframework.org/schema/beans/test=org.springframework.beans.factory.xml.support.TestNamespaceHandler 定义Handler: 主要注册相应的解析类和装饰类 publicclass TestNamespaceHandler extends NamespaceHandlerSupport { publicvoid init() { //相对于每个xsd中定义的元素 registerBeanDefinitionParser("testBean", new TestBeanDefinitionParser()); registerBeanDefinitionDecorator("set", new PropertyModifyingBeanDefinitionDecorator()); registerBeanDefinitionDecorator("debug", new DebugBeanDefinitionDecorator()); registerBeanDefinitionDecorator("nop", new NopInterceptorBeanDefinitionDecorator()); registerBeanDefinitionDecoratorForAttribute("object-name", new ObjectNameBeanDefinitionDecorator()); } } 定义各个解析类: privatestaticclass TestBeanDefinitionParser implements BeanDefinitionParser { public BeanDefinition parse(Element element, ParserContext parserContext) { RootBeanDefinition definition = new RootBeanDefinition(); definition.setBeanClass(TestBean.class); MutablePropertyValues mpvs = new MutablePropertyValues(); mpvs.addPropertyValue("name", element.getAttribute("name")); mpvs.addPropertyValue("age", element.getAttribute("age")); definition.setPropertyValues(mpvs); parserContext.getRegistry().registerBeanDefinition(element.getAttribute("id"), definition); returnnull; } } privatestaticclassPropertyModifyingBeanDefinitionDecorator implements BeanDefinitionDecorator { public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) { Element element = (Element)node; BeanDefinition def = definition.getBeanDefinition(); MutablePropertyValues mpvs = (def.getPropertyValues() == null) ? new MutablePropertyValues() : def.getPropertyValues(); mpvs.addPropertyValue("name", element.getAttribute("name")); mpvs.addPropertyValue("age", element.getAttribute("age")); ((AbstractBeanDefinition) def).setPropertyValues(mpvs); return definition; } } privatestaticclassDebugBeanDefinitionDecorator extends AbstractInterceptorDrivenBeanDefinitionDecorator { protected BeanDefinition createInterceptorDefinition(Node node) { returnnew RootBeanDefinition(DebugInterceptor.class); } } privatestaticclassNopInterceptorBeanDefinitionDecorator extends AbstractInterceptorDrivenBeanDefinitionDecorator { protected BeanDefinition createInterceptorDefinition(Node node) { returnnew RootBeanDefinition(NopInterceptor.class); } } privatestaticclassObjectNameBeanDefinitionDecorator implements BeanDefinitionDecorator { public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) { Attr objectNameAttribute = (Attr)node; definition.getBeanDefinition().setAttribute("objectName", objectNameAttribute.getValue()); return definition; } } 可以定义EntityResolver,用于验证相应的xsd privateclass DummySchemaResolver extends PluggableSchemaResolver { public DummySchemaResolver() { super(CustomNamespaceHandlerTests.this.getClass().getClassLoader()); } public InputSource resolveEntity(String publicId, String systemId) throws IOException { InputSource source = super.resolveEntity(publicId, systemId); if (source == null) { Resource resource = new ClassPathResource("org/springframework/beans/factory/xml/support/spring-test.xsd"); source = new InputSource(resource.getInputStream()); source.setPublicId(publicId); source.setSystemId(systemId); } return source; } } 关键的一步,如何生效: String location = "org/springframework/beans/factory/xml/support/customNamespace.properties"; NamespaceHandlerResolver resolver = new DefaultNamespaceHandlerResolver( getClass().getClassLoader(), location); DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory); reader.setNamespaceHandlerResolver(resolver); reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_XSD); reader.setEntityResolver(new DummySchemaResolver()); reader.loadBeanDefinitions(getResource()); 写一个测试xml文件: <?xmlversion="1.0"encoding="UTF-8"?> <beansxmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:test="http://www.springframework.org/schema/beans/test" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/beans/testhttp://www.springframework.org/schema/beans/factory/xml/support/spring-test.xsd"> <test:testBeanid="testBean"name="Rob Harrop"age="23"/> <beanid="customisedTestBean"class="org.springframework.beans.TestBean"> <test:setname="Rob Harrop"age="23"/> </bean> <beanid="debuggingTestBean"class="org.springframework.beans.TestBean"> <test:debug/> <propertyname="name"value="Rob Harrop"/> <propertyname="age"value="23"/> </bean> <beanid="chainedTestBean"class="org.springframework.beans.TestBean"> <test:debug/> <test:nop/> <propertyname="name"value="Rob Harrop"/> <propertyname="age"value="23"/> </bean> <beanid="decorateWithAttribute"class="org.springframework.beans.TestBean"test:object-name="foo"/> </beans> 相关的测试方法: publicvoid testSimpleParser() throws Exception { TestBean bean = (TestBean) this.beanFactory.getBean("testBean"); assetTestBean(bean); } publicvoid testSimpleDecorator() throws Exception { TestBean bean = (TestBean) this.beanFactory.getBean("customisedTestBean"); assetTestBean(bean); } publicvoid testProxyingDecorator() throws Exception { ITestBean bean = (ITestBean) this.beanFactory.getBean("debuggingTestBean"); assetTestBean(bean); assertTrue(AopUtils.isAopProxy(bean)); Advisor[] advisors = ((Advised) bean).getAdvisors(); assertEquals("Incorrect number of advisors", 1, advisors.length); assertEquals("Incorrect advice class.", DebugInterceptor.class, advisors[0].getAdvice().getClass()); } publicvoid testChainedDecorators() throws Exception { ITestBean bean = (ITestBean) this.beanFactory.getBean("chainedTestBean"); assetTestBean(bean); assertTrue(AopUtils.isAopProxy(bean)); Advisor[] advisors = ((Advised) bean).getAdvisors(); assertEquals("Incorrect number of advisors", 2, advisors.length); assertEquals("Incorrect advice class.", DebugInterceptor.class, advisors[0].getAdvice().getClass()); assertEquals("Incorrect advice class.", NopInterceptor.class, advisors[1].getAdvice().getClass()); } publicvoid testDecorationViaAttribute() throws Exception { RootBeanDefinition beanDefinition = (RootBeanDefinition)this.beanFactory.getBeanDefinition("decorateWithAttribute"); assertEquals("foo", beanDefinition.getAttribute("objectName")); } privatevoid assetTestBean(ITestBean bean) { assertEquals("Invalid name", "Rob Harrop", bean.getName()); assertEquals("Invalid age", 23, bean.getAge()); } 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2006-10-29
我初步觉得这种功能基本上实用性不大,但是作为一个框架,提供这种功能,在宣传上就又多了一个噱头。
|
|
返回顶楼 | |
发表时间:2006-10-29
spring的文档说得很清楚,这个功能是给第三方框架开发自己的schema用的,如果各个第三方框架都像<aop:> <tx:>那样提供简写,我们的配置文件就会简单一点。
|
|
返回顶楼 | |
发表时间:2006-10-30
江南白衣 写道 spring的文档说得很清楚,这个功能是给第三方框架开发自己的schema用的,如果各个第三方框架都像<aop:> <tx:>那样提供简写,我们的配置文件就会简单一点。
acegi适合这样做,能节约不少字数 compass已经这么做的 |
|
返回顶楼 | |
发表时间:2006-10-30
这是一个非常重要的特性。它使得spring可以成为DSL的框架,定义自己的语法。看看springRichClient中menu的定义多么复杂就知道多么需要这个特性了。死的框架是没有什么意思的,只有可以定义语法的元级框架才是王道。rails是很不错的,但是它只是分析清理和剪裁了需求的结果,真正的惊喜是ruby和无处不在的DSL思想。这点和spring1.2与spring2的区别很象。
|
|
返回顶楼 | |
发表时间:2006-10-30
myace 写道 这是一个非常重要的特性。它使得spring可以成为DSL的框架,定义自己的语法。看看springRichClient中menu的定义多么复杂就知道多么需要这个特性了。死的框架是没有什么意思的,只有可以定义语法的元级框架才是王道。rails是很不错的,但是它只是分析清理和剪裁了需求的结果,真正的惊喜是ruby和无处不在的DSL思想。这点和spring1.2与spring2的区别很象。
有道理 |
|
返回顶楼 | |
发表时间:2007-08-28
对于第三方是非常的有用的,比如dwr
|
|
返回顶楼 | |