欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring源码深度解析(第2版)- 自定义标签的使用

程序员文章站 2024-01-29 12:54:46
...

目录

一、前言

1.简介

2.工具版本

二、项目目录结构

三、自定义标签的使用

1.创建一个POJO

2.定义一个XSD文件描述组件内容

3.创建一个类,继承AbstractSingleBeanDefinitionParser接口,用来解析XSD文件中的定义和组件定义。

4.建一个Handler文件,扩展自NamespaceHandlerSupport,目的是将组件注册到Spring容器。

5.编写Spring.handlers和Spring.schemas文件

6.创建测试配置文件,在配置文件中引入对应的命名空间以及XSD后,便可以直接使用自定义标签了。

7.测试


一、前言

1.简介

《Spring源码深度解析(第2版)》第4章默认标签的解析第1节自定义标签的使用,在学习解析之前需要先了解一下自定标签的使用过程。本文按照书中自定义标签的内容进行测试。

2.工具版本:

IntelliJ IDEA 2019.1.2

java version "1.8.0_77"

Spring version 5.2.0.BUILD-SNAPSHOT

二、项目目录结构

只需要看红色边框内的文件(在下载的源码中新增一个模块用来测试)

Spring源码深度解析(第2版)- 自定义标签的使用

三、自定义标签的使用

        在很多情况下,我们需要为系统提供可配置化支持,简单的做法可以直接基于Spring的标准bean来配置,但配置较为复杂或者需要更多丰富控制的时候,会显得非常笨拙。一般的做法会用原生态的方式去解析定义好的XML文件,然后转化为配置对象。这种方式当然可以解决所有问题,但实现起来比较烦琐,特别是在配置非常复杂的时候,解析工作是一个不得不考虑的负担。Spring 提供了可扩展Schema的支持,这是一个不错的折中方案,扩展Spring自定义标签配置大致需要以下几个步骤(前提是要把Spring 的Core包加入项目中)。

  • 创建一个需要扩展的组件。
  • 定义一个XSD文件描述组件内容。
  • 创建一个文件,实现BeanDefinitionParser接口,用来解析XSD文件中的定义和组件
  • 定义。
  • 创建一个Handler文件,扩展自NamespaceHandlerSupport,目的是将组件注册到Spring
  • 容器。
  • 编写Spring.handlers和Spring.schemas文件。
  • 现在我们就按照上面的步骤带领读者一步步地体验自定义标签的过程。

1.创建一个POJO

User

package com.asyf.chapter04;

public class User {

	private String id;

	private String userName;

	private String email;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	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{" +
				"id='" + id + '\'' +
				", userName='" + userName + '\'' +
				", email='" + email + '\'' +
				'}';
	}
}

2.定义一个XSD文件描述组件内容

user.xsd

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

	<element name="user">
		<complexType>
			<attribute name="id" type="string"/>
			<attribute name="userName" type="string"/>
			<attribute name="email" type="string"/>
		</complexType>
	</element>

</schema>

3.创建一个类,继承AbstractSingleBeanDefinitionParser接口,用来解析XSD文件中的定义和组件定义。

package com.asyf.chapter04;

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 UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

	// Element对应的类
	protected Class getBeanClass(Element element) {
		return User.class;
	}

	// 从element中解析并提取对应的元素
	protected void doParse(Element element, BeanDefinitionBuilder beanDefinitionBuilder) {
		String id = element.getAttribute("id");
		String userName = element.getAttribute("userName");
		String email = element.getAttribute("email");
		// 将提取的数据放到BeanDefinitionBuilder中,待完成所有bean的解析后统一注册到BeanFactory中
		if (StringUtils.hasText("id")) {
			beanDefinitionBuilder.addPropertyValue("id", id);
		}
		if (StringUtils.hasText(userName)) {
			beanDefinitionBuilder.addPropertyValue("userName", userName);
		}
		if (StringUtils.hasText(email)) {
			beanDefinitionBuilder.addPropertyValue("email", email);
		}
	}

}

注意:书中写的是:创建一个文件,实现BeanDefinitionParser接口,用来解析XSD文件中的定义和组件定义。查看类图,AbstractSingleBeanDefinitionParser实现BeanDefinitionParser接口。

Spring源码深度解析(第2版)- 自定义标签的使用

4.建一个Handler文件,扩展自NamespaceHandlerSupport,目的是将组件注册到Spring容器。

package com.asyf.chapter04;

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

public class MyNamespaceHandler extends NamespaceHandlerSupport {

	@Override
	public void init() {
		registerBeanDefinitionParser("user", new UserBeanDefinitionParser());
	}

}

5.编写Spring.handlers和Spring.schemas文件

默认位置是在工程的/META-INF/文件夹下,当然,你可以通过Spring 的扩展或者修改源码的方式改变路径。

  • spring.handlers

http\://www.lexueba.com/schema/user=com.asyf.chapter04.MyNamespaceHandler

  • spring.schemas

http\://www.lexueba.com/schema/user.xsd=META-INF/user.xsd

6.创建测试配置文件,在配置文件中引入对应的命名空间以及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:myname="http://www.lexueba.com/schema/user"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.lexueba.com/schema/user http://www.lexueba.com/schema/user.xsd">

    <myname:user id="testbean" userName="aaa" email="aaa@qq.com"/>

</beans>

7.测试

package com.asyf.chapter04;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

public class MyTest {

	public static void main(String[] args) {
		BeanFactory bf = new XmlBeanFactory(new ClassPathResource("test.xml"));
		User user = (User) bf.getBean("testbean");
		System.out.println(user.toString());
	}

}

Console打印:

Spring源码深度解析(第2版)- 自定义标签的使用

测试完毕。