关于spring 2.0自定义xml 标记 (二 如何实现)

    技术2022-05-11  46

     www.javabc.com

    看了spring test 用例,其实实现这一功能还算比较简单,主要分以下的步骤,具体的实例可以去参考spring 自带的testcase

    首先定义相关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());

        }


    最新回复(0)