spring2.x自定义标签

来源:互联网 发布:win10 未识别的网络 编辑:程序博客网 时间:2024/06/05 09:41

  作为一般的应用程序开发人员,扩展spring的标签意义不大。
  但如果你是一个平台开发人员,则很有必要拥有一套自己的标签,提供给应用开发人员使用,因为走秀网需要搭建一个mq平台,简化配置信息,所以要扩展spring的标签。

  1. <xiu:datasource id= "datasource"     
  2.        databaseType= "oracle"     
  3.        ip= "192.168.80.82"     
  4.        port= "1521"     
  5.        databaseName= "orcl"   
  6.        userName= "xiu_sms"   
  7.        password= "xiu_sms"   
  8.        />   
  9.   
  10. <xiu:ehCache id= "xiu"     
  11.        cache= "true"     
  12.        maxElements= "100000"     
  13.        timeToIdleSeconds= "120"     
  14.        timeToLiveSeconds= "120"   
  15.        overflowToDisk= "true"         
  16. />   

上面的代码中配置了两个组件,datasourcecache组件,相比普通的beanpropertiy方式,很显然,这种配置方式更直观,更易读,更重要的是,如果作为组件发布,使用者也可以很方便快捷的开始使用,而不需要关心组件的任何实现细节。

 

扩展spring自定义标签配置大致需要一下几个步骤(前提是要把springcore包加入项目中)
1
、创建一个需要扩展的组件 
2
、定义一个xsd文件描述组件内容 
3
、创建一个文件,实现BeanDefinitionParser接口,用来解析xsd文件中的定义和组件定义 
4
、创建一个Handler文件,扩展自NamespaceHandlerSupport,目的是将组件注册到Spring容器 
5
、编写spring.handlersspring.schemas文件

提供一个简单的例子,来说明如何去扩展一个Spring配置,需求如下:使用自定义标签定义一个简单的bean,这个bean有一个或多个属性,标签定义完成后,可以在其他项目中用自定义标签来定义该bean

首先,创建一个需要扩展的组件,在这里只是一个简单的bean,bean中有3个属性。

  

代码:

package com.xiu.tag;
public class DataSourceBean {
      private Stringurl;
      private Stringdbname;
      private StringmaxIndex;
      public StringgetUrl() {
           return url;
      }
      public voidsetUrl(String url) {
           this.url =url;
      }

      public StringgetDbname() {
           returndbname;
      }
      public voidsetDbname(String dbname) {
           this.dbname =dbname;
      }
      public StringgetMaxIndex() {
           returnmaxIndex;
      }
      public voidsetMaxIndex(String maxIndex) {
           this.maxIndex= maxIndex;
      }
}

 

然后,建立一个xsd文件,来描述这个bean 
data.xsd

代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schemaxmlns="http://www.xiu.com/schema/data"
      xmlns:xsd="http://www.w3.org/2001/XMLSchema"
      xmlns:beans="http://www.springframework.org/schema/beans"
      targetNamespace="http://www.xiu.com/schema/data"
      elementFormDefault="qualified"attributeFormDefault="unqualified">
      <xsd:import
           namespace="http://www.springframework.org/schema/beans">
      </xsd:import>
      <xsd:elementname="DataSourceBean">
           <xsd:complexType>
                 <xsd:complexContent>
                      <xsd:extensionbase="beans:identifiedType">
                            <xsd:attributename="url" type="xsd:string"
                                  default="www.xiu.com"/>
                            <xsd:attributename="dbname" type="xsd:string"
                                  default="orcl"/>
                            <xsd:attributename="maxIndex" type="xsd:string"
                                  default="100" />
                      </xsd:extension>
                 </xsd:complexContent>
           </xsd:complexType>
      </xsd:element>
</xsd:schema>

           在上面的xsd文件描述了一个新的targetNamespace,并在这个空间中定义了一个nameDataSourceBeanelement,one有三个属性url,dbnamne,maxIndex类型为string,而且都有默认值.xsd文件是xml DTD的替代者,使用XML Schema语言进行编写,这里对xsd schema不做太多解释,有兴趣可以参考相关的资料。

 

创建一个Java文件,该文件实现了BeanDefinitionParser接口,用来解析xsd文件中的定义并注册到组件中

XiuBeanDefinitionParser.java

代码如下:

package com.xiu.tag;
importorg.springframework.beans.factory.config.BeanDefinition;
importorg.springframework.beans.factory.config.BeanDefinitionHolder;
importorg.springframework.beans.factory.support.BeanDefinitionReaderUtils;
importorg.springframework.beans.factory.support.RootBeanDefinition;
importorg.springframework.beans.factory.xml.BeanDefinitionParser;
importorg.springframework.beans.factory.xml.ParserContext;
importorg.w3c.dom.Element;
public classXiuBeanDefinitionParser implements BeanDefinitionParser {
      public BeanDefinition parse(Elementelement, ParserContext parserContext) {
           // 设置 Bean Class也就是DataSourceBean
           RootBeanDefinition rdef = newRootBeanDefinition();
           rdef.setBeanClass(DataSourceBean.class);
          
           // 注册id属性,没人是有id属性,在xsd文件中可以不用声明
           // 但是在注册时必须要注入
           String id =element.getAttribute("id");
           BeanDefinitionHolderidDefinitionHolder = new BeanDefinitionHolder(
                      rdef, id);
           BeanDefinitionReaderUtils.registerBeanDefinition(idDefinitionHolder,
                      parserContext.getRegistry());


           // 注册url属性
           String url =element.getAttribute("url");
           BeanDefinitionHolderurlDefinitionHolder = new BeanDefinitionHolder(
                      rdef, url);
           BeanDefinitionReaderUtils.registerBeanDefinition(urlDefinitionHolder,
                      parserContext.getRegistry());
           rdef.getPropertyValues().addPropertyValue("url",url);
          
           // 注册dbname属性
           String dbName =element.getAttribute("dbname");
           BeanDefinitionHolderdbNameDefinitionHolder = new BeanDefinitionHolder(
                      rdef, dbName);
           BeanDefinitionReaderUtils.registerBeanDefinition(dbNameDefinitionHolder,
                      parserContext.getRegistry());
            rdef.getPropertyValues().addPropertyValue("dbname",dbName);
          
           // 注册maxIndex属性
           String maxIndex =element.getAttribute("maxIndex");
           BeanDefinitionHoldermaxIndexDefinitionHolder = new BeanDefinitionHolder(
                      rdef, maxIndex);
           BeanDefinitionReaderUtils.registerBeanDefinition(maxIndexDefinitionHolder,
                      parserContext.getRegistry());
           rdef.getPropertyValues().addPropertyValue("maxIndex",maxIndex);
          
           return rdef;

      }

}

上面的代码仅仅实现了一个方法publicBeanDefinition parse(Element element, ParserContext parserContext),设置相关的Bean Class,解析了对应的xsd文件,并将解析的内容注册到上下文中,同时返回一个BeanDefinition对象(BeanDefinitionSpringbean定义,提供了bean部分的操作方法,如isSingleton()isLazyInit())

注意,id属性是一个默认的属性,可以不在xsd文件中描述,但是需要注册它,否则将无法通过getBean方法获取标签定义的bean,也无法被其他bean引用。 
另外,下面代码是给bean的属性赋值,这个是不可缺少的,否则在使用标签定义时将无法获取bean属性的值。 

代码

rdef.getPropertyValues().addPropertyValue("maxIndex",maxIndex);  

 

然后为组件编写一个Handler文件,扩展自NamespaceHandlerSupport,它的作用是将组件注册到Spring容器 

XiuNameSpaceHandler.java

代码如下:

package com.xiu.tag;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;

public classXiuNameSpaceHandler extends NamespaceHandlerSupport{

      public void init() {
          
           registerBeanDefinitionParser("DataSourceBean",newXiuBeanDefinitionParser());
          
      }
}

 

 实际执行的过程只有一句代码,注册了一个名字为DataSourceBean的扩展配置,包含了XiuBeanDefinitionParser parser相关xsd的内容。

 

 

   到了这里,一个Spring扩展标签已经完成,但是我们目前还没办法使用它,Spring没那么聪明,它无法知道我们在什么地方定义了哪些扩展标签,这些标签将被谁解析,这个过程要我们通过一些文件来告知Spring知道,它们就是spring.handlersspring.schemas,它们放在META-INF目录中,Spring.jarMETA-INF目录中也有同名的文件,它们的文件内容基本上是相似的,而Spring在执行过程中,如果发现其他jar文件的META-INF文件夹中包含有这两个文件,Spring将会合并它们。 
spring.schemas 

代码

  1. http\://www.xiu.com/schema/data.xsd=com/xiu/tag/data.xsd   // http后面的斜杠表示转义字符

spring.handlers 

代码

  1. http\://www.xiu.com/schema/data=com.xiu.tag.XiuNameSpaceHandler   

spring.schemas将告诉Spring配置文件知道,如果在配置中引用http://www.xiu.com/schema/data.xsd,它应该去什么地方找相应的xsd文件。 
spring.handlers文件将告诉Spring,应该使用哪个Handler注册扩展标签。

现在为止,一个完整的xml扩展标签全部完成,做一个小应用测试一下。 

applicationContext.xml文件

<?xmlversion="1.0" encoding="UTF-8"?>
<beans
      xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:xiu="http://www.xiu.com/schema/data"
      xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
      http://www.xiu.com/schema/data 

       http://www.xiu.com/schema/data.xsd">  红色的url表示要增加的

<xiu:DataSourceBean id="oneBean" url="99"/>


</beans>

 

测试类

package com.xiu.tag;
importorg.springframework.context.ApplicationContext;
importorg.springframework.context.support.ClassPathXmlApplicationContext;

public classMain {
      public static void main(String[] args) {  
       ApplicationContext ctx = newClassPathXmlApplicationContext("applicationContext.xml");  
       DataSourceBean tag = (DataSourceBean)ctx.getBean("oneBean");   
       System.out.println("oneBean age is "+tag.getUrl());  
       System.out.println("oneBean age is "+tag.getDbname());  
       System.out.println("oneBean age is "+tag.getMaxIndex());  
   }   
}

 

输出结果

oneBean age is 99
oneBean ageis orcl
oneBean ageis 100

 


 

 

原创粉丝点击