Spring自定义标签

时间:2022-08-20 20:36:31

基础知识:

Spring默认会将xml中所有等标签解析为BeanDefinition的抽象,自定义标签的本质是扩展Spring自身的标签,使其从自定义标签转化为BeanDefinition的过程。

自定标签创建过程:
1.创建映射标签实体JavaBean: Person/User

package com.zhiwei.basic.tag;

import java.util.List;

public class Person {

private String personName;

private Integer age;

private List<String> nickName;

public String getPersonName() {
return personName;
}

public void setPersonName(String personName) {
this.personName = personName;
}

public Integer getAge() {
return age;
}

public void setAge(Integer age) {
this.age = age;
}

public List<String> getNickName() {
return nickName;
}

public void setNickName(List<String> nickName) {
this.nickName = nickName;
}

@Override
public String toString() {
return "Person [name=" + personName + ", age=" + age + ", nickName=" + nickName + "]";
}

}
package com.zhiwei.basic.tag;

public class User {

private String userName;

private String email;

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

@Override
public String toString() {
return "User [userName=" + userName + ", email=" + email + "]";
}
}

2.创建标签解析器

package com.zhiwei.basic.tag;

import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;

/**
* XML中的Bean标签解析器:将<dubbo:user>解析为User对象
*
*/

public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

@Override
protected Class<User> getBeanClass(Element element) {

return User.class;
}

@Override
protected void doParse(Element element, BeanDefinitionBuilder bean) {

String userName = element.getAttribute("userName");

String email = element.getAttribute("email");

if (StringUtils.hasText(userName)) {
bean.addPropertyValue("userName", userName);
}

if (StringUtils.hasText(email)) {
bean.addPropertyValue("email", email);
}
}
}
package com.zhiwei.basic.tag;

import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;

/**
* XML中的Bean标签解析器:将<dubbo:user>解析为User对象
*
*/

public class PersonBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

protected Class<Person> getBeanClass(Element element) {

return Person.class;
}

protected void doParse(Element element, BeanDefinitionBuilder bean) {

String userName = element.getAttribute("personName");

String email = element.getAttribute("age");

String nickName = element.getAttribute("nickName");

if (StringUtils.hasText(userName)) {
bean.addPropertyValue("personName", userName);
}

if (StringUtils.hasText(email)) {
bean.addPropertyValue("age", email);
}

if (StringUtils.hasText(nickName)) {
bean.addPropertyValue("nickName", nickName);
}
}

}

3.创建命名空间处理器:NamespaceHandler

package com.zhiwei.basic.tag;  

import org.springframework.beans.factory.xml.NamespaceHandlerSupport;

/**
* 命名空间处理器:
*/

public class NamespaceHandler extends NamespaceHandlerSupport {

/**
* DefaultBeanDefinitionDocumentReader调用
* 调用时间:自定义元素定义之后,自定义元素真正被解析之前
*/

@Override
public void init() {

registerBeanDefinitionParser("user", new UserBeanDefinitionParser());

registerBeanDefinitionParser("person", new PersonBeanDefinitionParser());
}
}

4.创建自定义标签的XML约束文件:XSD

<?xml version="1.0" encoding="UTF-8"?>  
<xsd:schema xmlns="http://www.zhiwei.com/schema/user"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.zhiwei.com/schema/user"
elementFormDefault="qualified"
attributeFormDefault="unqualified">


<!-- 定义标签元素及其类型 -->
<xsd:element name="user" type="user" />

<!-- 定义标签元素的类型 -->
<xsd:complexType name="user">
<xsd:attribute name="id" type="xsd:string" />
<xsd:attribute name="userName" type="xsd:string" default="zhangsan"/>
<xsd:attribute name="email" type="xsd:string" />
</xsd:complexType>

<xsd:element name="person" type="person" />

<xsd:complexType name="person">
<xsd:attribute name="id" type="xsd:string" />
<xsd:attribute name="personName" type="xsd:string"/>
<xsd:attribute name="age" type="xsd:integer"/>
<xsd:attribute name="nickName" type="nickName"/> <!-- 属性引用时name和ref属性不能同时出现 -->
</xsd:complexType>

<xsd:simpleType name="nickName">
<xsd:list itemType="xsd:string"/>
</xsd:simpleType>
</xsd:schema>

5.在项目的根类路径配置自定义标签命名空间、解析器等信息: META-INF

注意:文件名这2个文件名不能自定义修改,Spring框架内部对文件名进行了硬编码指定。

spring.handlers

http\://www.zhiwei.com/schema/user=com.zhiwei.basic.tag.NamespaceHandler

spring.schemas

http\://www.zhiwei.com/schema/user/user.xsd=com/zhiwei/basic/tag/user.xsd

6.测试自定义标签
Spring配置文件:

<?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:dubbo="http://www.zhiwei.com/schema/user"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.zhiwei.com/schema/user http://www.zhiwei.com/schema/user/user.xsd"
>


<dubbo:user id="user" userName="cong" email="mail.163.com"/>

<!-- 定义List类型的Bean -->
<dubbo:person id="person" personName="zhangsan" age="10" nickName="zhangsan,lisi,wangwu"/>
</beans>

测试类:

package com.zhiwei.basic.tag;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainTest {

@SuppressWarnings("resource")
public static void main(String[] args) {

ApplicationContext ac = new ClassPathXmlApplicationContext("com/zhiwei/basic/tag/applicationContext.xml");

User user = (User) ac.getBean("user");

System.out.println("user--------" + user);

Person person = (Person) ac.getBean("person");

System.out.println("person---------"+person);
}
}

效果:
Spring自定义标签

项目层次图:
Spring自定义标签