可以通过扩展Spring的Schema,来实现自定义配置。完成一个自定义配置一般需要完成下面的步骤:
下面是我测试的项目结构:
package cn.timd.spring.spring_schema; public class Person { private String id; //id默认是需要的 private String name; private Integer age; public Person() { } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "Person{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", age=" + age + '}'; } }
<?xml version="1.0" encoding="UTF-8" ?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://timd.cn/schema/person" targetNamespace="http://timd.cn/schema/person" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xsd:import namespace="http://www.springframework.org/schema/beans"></xsd:import> <xsd:element name="person"> <xsd:complexType> <xsd:complexContent> <xsd:extension base="beans:identifiedType"> <xsd:attribute name="name" type="xsd:string"></xsd:attribute> <xsd:attribute name="age" type="xsd:int"></xsd:attribute> </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:element> </xsd:schema>
关于xsd的详细信息,可查看:http://www.w3school.com.cn/schema/index.asp。
完成后,需要把xsd放到CLASSPATH下,一般都放在META-INF目录下。
NamespaceHandler类负责根据schema和节点找到相应的BeanDefinitionParser,然后由BeanDefinitionParser完成具体的解析工作。
因此需要分别完成NamespaceHandler和BeanDefinitionParser的实现类,Spring提供了默认实现类NamespaceHandlerSupport和AbstractSingleBeanDefinitionParser,简单的方式就是去继承这两个类。
package cn.timd.spring.spring_schema; import org.springframework.beans.factory.xml.NamespaceHandlerSupport; public class PersonNamespaceHandler extends NamespaceHandlerSupport { public void init(){ registerBeanDefinitionParser("person", new PersonBeanDefinitionParser()); } }
registerBeanDefinitionParser用来把节点名和解析类关联起来
package cn.timd.spring.spring_schema; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.util.StringUtils; import org.w3c.dom.Element; public class PersonBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { protected Class> getBeanClass(Element element) { return Person.class; } protected void doParse(Element ele, BeanDefinitionBuilder bean) { String id = ele.getAttribute("id"); String name = ele.getAttribute("name"); String age = ele.getAttribute("age"); if (StringUtils.hasText(id)) bean.addPropertyValue("id", Integer.valueOf(id)); if (StringUtils.hasText(name)) bean.addPropertyValue("name", name); if (StringUtils.hasText(age)) bean.addPropertyValue("age", Integer.valueOf(age)); } }
ele.getAttribute用于从配置中取得属性值,bean.addPropertyValue用于把属性值放到bean中
spring.handlers和spring.schemas用于串联所有的组件---xsd文件、NamespaceHandler类以及BeanDefinitionParser类。这两个文件必须放在META-INF下(xsd文件可以放在META-INF下,也可以放在类路径下)。
http\://timd.cn/schema/person=cn.timd.spring.spring_schema.PersonNamespaceHandler
http\://timd.cn/schema/person/person.xsd=META-INF/person.xsd
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:person="http://timd.cn/schema/person" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://timd.cn/schema/person http://timd.cn/schema/person/person.xsd"> <person:person name="timchow" age="28" id="10086"></person:person> </beans>
package cn.timd.spring.spring_schema; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); Person person = (Person) ctx.getBean("10086"); System.out.println(person); } }