從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工程