目錄
一、前言
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的标準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接口。
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="[email protected]"/>
</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列印:
測試完畢。