`
zyl
  • 浏览: 486272 次
社区版块
存档分类
最新评论

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

阅读更多
看了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());

    }
分享到:
评论
9 楼 fu80008 2007-08-28  
对于第三方是非常的有用的,比如dwr
8 楼 lighter 2006-10-30  
myace 写道
这是一个非常重要的特性。它使得spring可以成为DSL的框架,定义自己的语法。看看springRichClient中menu的定义多么复杂就知道多么需要这个特性了。死的框架是没有什么意思的,只有可以定义语法的元级框架才是王道。rails是很不错的,但是它只是分析清理和剪裁了需求的结果,真正的惊喜是ruby和无处不在的DSL思想。这点和spring1.2与spring2的区别很象。

有道理
7 楼 myace 2006-10-30  
这是一个非常重要的特性。它使得spring可以成为DSL的框架,定义自己的语法。看看springRichClient中menu的定义多么复杂就知道多么需要这个特性了。死的框架是没有什么意思的,只有可以定义语法的元级框架才是王道。rails是很不错的,但是它只是分析清理和剪裁了需求的结果,真正的惊喜是ruby和无处不在的DSL思想。这点和spring1.2与spring2的区别很象。
6 楼 quaff 2006-10-30  
江南白衣 写道
spring的文档说得很清楚,这个功能是给第三方框架开发自己的schema用的,如果各个第三方框架都像<aop:> <tx:>那样提供简写,我们的配置文件就会简单一点。

acegi适合这样做,能节约不少字数
compass已经这么做的
5 楼 江南白衣 2006-10-29  
spring的文档说得很清楚,这个功能是给第三方框架开发自己的schema用的,如果各个第三方框架都像<aop:> <tx:>那样提供简写,我们的配置文件就会简单一点。
4 楼 quickselect 2006-10-29  
   我初步觉得这种功能基本上实用性不大,但是作为一个框架,提供这种功能,在宣传上就又多了一个噱头。
3 楼 Lincoln 2006-10-29  
跟顶!~
2 楼 小贾 2006-10-28  
不错!项目中正用着spring,学习一下!
1 楼 江南白衣 2006-10-27  
再顶!!

相关推荐

    Spring 2.0 源代码

    2. **AOP(面向切面编程)**:Spring 2.0提供了更强大的面向切面编程支持,允许开发者定义切面、通知(advisors)和切点(pointcuts),并将其应用于业务代码,实现如日志、事务管理等功能。切面可以是接口、类或...

    spring2.0技术手册_源代码(全十章)

    DI是Spring的核心特性,通过源码,我们可以学习到如何定义bean的配置,如何使用`@Autowired`和`@Qualifier`注解实现自动装配,以及如何自定义bean的生命周期。对于AOP,可以研究`@Aspect`和`@Pointcut`注解,理解切...

    spring2.0中文教程参考文档

    1. Bean管理:Spring 2.0强化了Bean的生命周期管理,支持基于注解的配置(@Component、@Service、@Repository、@Controller),简化了XML配置,使得代码更加简洁。 2.依赖注入(DI):通过@Autowired注解,Spring...

    Spring2.0 API

    Spring 2.0引入了大量的注解,如`@Autowired`、`@Service`、`@Repository`和`@Controller`,使得开发者可以摆脱XML配置,实现更简洁的依赖注入。`@Autowired`自动匹配类型,减少手动装配工作;`@Component`、`@...

    Spring Boot 2.0官方参考文档

    ### Spring Boot 2.0官方参考文档知识点梳理 #### 一、Spring Boot 2.0简介与系统需求 - **Spring Boot**是一个基于Spring框架的全新子项目,它旨在简化新Spring应用的初始搭建以及开发过程。该版本为2.0.0.BUILD-...

    Spring Data JPA 2.0 标准模板

    **Spring Data JPA 2.0 标准模板详解** Spring Data JPA 是 Spring 框架的一个子项目,它简化了数据访问层的开发,提供了对 Java Persistence API(JPA)的高度抽象和自动化。在 Spring Data JPA 2.0 版本中,它...

    Spring教材

    Spring 2.0增强了XML配置的扩展性,允许用户自定义命名空间和元素,方便构建自己的配置元数据。 - **Annotation驱动配置** Spring 2.0引入了注解支持,如`@Component`、`@Service`、`@Repository`和`@Controller...

    SPRING 开发指南

    Spring 2.0引入了扩展XML配置的能力,允许自定义解析器和元素,这增强了Spring配置的灵活性,开发者可以根据项目需求定制自己的配置元素。 7. **Aspect-Oriented Programming (AOP)**: Spring提供了对面向切面...

    jsp+xml的一个小demo

    XML文档可以包含自定义的标签来描述数据,这使得XML成为跨平台和应用程序间数据交换的理想选择。 【JSP与XML的结合】 1. **JSP中的XML处理** JSP可以通过使用JSP动作元素(JSP Actions)如`&lt;jsp:include&gt;`、`...

    Spring和openJPA集成

    6. **事务管理**:Spring 的事务管理能力使得可以在方法级别控制事务,例如使用 `@Transactional` 注解标记需要事务的方法。 7. **测试**:编写测试用例验证集成是否正确,确保数据持久化和事务管理等功能正常工作...

    spring3.0依赖注入详解

    除了内置的注解,Spring还支持自定义注解,只需在自定义注解上添加`@Component`注解,即可赋予其标记Bean的能力。虽然这一特性不常用,但它展示了Spring的高度灵活性。 ##### BeanNameGenerator与自定义命名策略 ...

    pager-taglib-2.0.rar

    "pager-taglib-2.0" 是一个强大且灵活的分页标记库,它简化了Web开发中的分页实现,使得开发者能够快速地构建出类似大型网站的分页功能。其易于集成、高度定制化和良好的性能表现,使得它成为Java Web开发中的一个...

    2021年springboot2.0 入门到精通

    在本文中,我们将深入探讨SpringBoot 2.0的基础知识,以及...这仅仅是SpringBoot功能的冰山一角,随着学习的深入,你会发现更多关于SpringBoot的高级特性和最佳实践,如健康检查、自定义配置、安全管理和云原生支持等。

    UrlRewriter Java v2.0 RC1

    4. **自定义标记**:扩展系统,创建自定义的重写标记,以满足特定的应用场景需求。 5. **与Web框架集成**:与Spring MVC、Struts、JSF等常见Java Web框架兼容,方便集成。 6. **性能优化**:设计上考虑了性能,...

    springBoot2.0+mybatis支持多数据源+shiro

    **SpringBoot 2.0**:这是Spring框架的一个子项目,旨在简化Spring应用的初始搭建以及开发过程。它预配置了许多常见的设置,如服务器、数据库、MVC、安全等,使得开发者能够快速上手并专注于业务逻辑。SpringBoot ...

    spring annotation 入门

    Spring 框架自2.0 版本起引入了一系列注解支持,这极大简化了配置管理,并为开发提供了更为简洁灵活的方式。通过注解,可以将业务逻辑与配置分离,减少XML配置文件的编写工作,提高开发效率。 #### 二、核心注解...

    springboot备课.doc

    - **自动配置**:开箱即用,对Spring进行大量预设配置,但同时也允许自定义配置。 - **生产就绪**:包括性能监控、健康检查、外部配置等功能。 - **无XML配置**:强调Java配置,避免XML配置文件。 【Java配置...

    jsp2_0技术手册

    1. **页面元素**:JSP页面由HTML或XML标记和JSP元素组成,包括指令、脚本元素和动作元素。例如,`&lt;jsp:include&gt;`用于在页面中插入其他文件,`&lt;jsp:useBean&gt;`用于实例化JavaBean。 2. **指令**:如`&lt;%@ page %&gt;`, `...

    最新版本ssh搭好的框架模板

    在Hibernate 4中,性能得到了提升,支持JPA 2.0规范,并引入了更好的二级缓存机制。例如,我们可以使用@Entity注解来标记实体类,@Id表示主键,@GeneratedValue指定主键生成策略。通过SessionFactory和Session接口,...

Global site tag (gtag.js) - Google Analytics