从spring 2.0开始,spring开始支持基于schema的bean的配置和定义,即经过标签订义和配置bean交由spring容器管理,它和经过spring的<bean>标签订义bean是相同的,但对于用户更透明和友好。html
例如,须要配置User bean,经过spring提供的bean标签配置以下:java
<bean class="com.github.thinwonton.spring.schema.User"> <property name="name" value="hugo"></property> <property name="age" value="18"></property> <property name="addr" value="中国"></property> <property name="gender" value="male"></property> </bean>
若是gender属性只接受male和female,这在bean标签中是不可控的,但咱们经过自定义扩展spring的bean标签后,能够作到属性可控。另外,哪些是必须的,哪些是可选的,这均可以经过自定义标签作到。git
<test:user id="userBean" name="hugo" age="18" addr="中国" gender="male" />
想写自定义标签,但首先须要了解 XML Schema Definition(XSD) ,这里仅对一些遇到的标签说明,其它请各位自学。github
http://www.runoob.com/schema/schema-tutorial.htmlspring
** 自定义一个自定义标签mytag.xsd,其中一个元素节点为user,元素有四个属性分别是name、age、addr、gender,其中name/age/addr为必须填写的,gender是可选的而且是枚举类型。 **网络
spring官方文档详细地说明了扩展schema标签的步骤,若是英文好的话能够去看看,不行的话那往下看吧。 http://docs.spring.io/spring/docs/4.2.9.RELEASE/spring-framework-reference/htmlsingle/#extensible-xml-introductioneclipse
实现以上需求须要完成如下步骤:ide
先看一下完成需求后的工程结构:测试
(1)设计配置属性和JavaBeanui
//User.java package com.github.thinwonton.spring.schema; public class User { private String name; private int age; private String addr; private String gender; //忽略getter/setter @Override public String toString() { return "User [name=" + name + ", age=" + age + ", addr=" + addr + ", gender=" + gender + "]"; } }
(2)编写XSD文件,定义标签的属性。xsd文件名:mytag.xsd。
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns="http://www.github.com/thinwonton/schema/mytag" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans" targetNamespace="http://www.github.com/thinwonton/schema/mytag" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xsd:import namespace="http://www.springframework.org/schema/beans" /> <!-- xsd:element 表示定义标签 --> <xsd:element name="user"> <xsd:complexType> <xsd:complexContent> <!-- 继承定义 从namespace="http://www.springframework.org/schema/beans" --> <xsd:extension base="beans:identifiedType"> <!-- 定义name属性,string类型,必须 --> <xsd:attribute name="name" type="xsd:string" use="required" /> <!-- 定义age属性,无符号int类型,必须 --> <xsd:attribute name="age" type="xsd:unsignedInt" use="required" /> <!-- 定义addr属性,string类型,必须 --> <xsd:attribute name="addr" type="xsd:string" use="required" /> <!-- 定义gender属性,枚举类型,默认值是male,可选 --> <xsd:attribute name="gender" use="optional" default="male"> <xsd:simpleType> <xsd:restriction base="xsd:string"> <xsd:enumeration value="male" /> <xsd:enumeration value="female" /> </xsd:restriction> </xsd:simpleType> </xsd:attribute> </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:element> </xsd:schema>
说明:
(3) 编写NamespaceHandler和BeanDefinitionParser完成解析工做
//UserBeanDefinitionParser.java public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { @Override protected Class<?> getBeanClass(Element element) { return User.class; } @Override protected void doParse(Element element, BeanDefinitionBuilder builder) { // 获取属性 String name = element.getAttribute("name"); int age = Integer.parseInt(element.getAttribute("age")); String addr = element.getAttribute("addr"); String gender = element.getAttribute("gender"); // 给bean赋值 builder.addPropertyValue("name", name); builder.addPropertyValue("age", age); builder.addPropertyValue("addr", addr); builder.addPropertyValue("gender", gender); } }
public class MytagNamespaceHandler extends NamespaceHandlerSupport { @Override public void init() { //"user"对应于xsd文件里面的<xsd:element name="user"> //这里的意思是告诉spring使用UserBeanDefinitionParser解析器解析user这个元素 registerBeanDefinitionParser("user", new UserBeanDefinitionParser()); } }
(4)编写spring.handlers和spring.schemas文件,串联起全部部件
spring.schemas文件,把命令空间与工程中的具体定义文件相关联
http\://www.github.com/thinwonton/schema/mytag/mytag.xsd=META-INF/mytag.xsd
spring.handlers文件,告诉spring该让哪一个命令空间处理器处理xsd定义的一堆元素
http\://www.github.com/thinwonton/schema/mytag=com.github.thinwonton.spring.schema.MytagNamespaceHandler
(5)在spring配置文件中引用
引入schema,把schema的命令空间给一个缩写名mytag
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mytag="http://www.github.com/thinwonton/schema/mytag" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.github.com/thinwonton/schema/mytag http://www.github.com/thinwonton/schema/mytag/mytag.xsd "> <mytag:user id="userBean" name="hugo" age="18" addr="中国" gender="male" /> </beans>
这里可能发生命名控件不能识别的问题,这是由于咱们的文件没有上传到网络上,这时咱们须要在eclipse中指定命令空间的解析地址映射到本地文件中。
测试:
public class Main { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring-context.xml"); User user = context.getBean(User.class); System.out.println(user.toString()); } }
https://git.oschina.net/thinwonton/spring-showcase.git
项目里的spring-schema-extend工程