一、自定义标签
- 建立model
package com.demo3;
/**
*
* @author dqf
* @since 5.0
*/
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;
}
}
- 定义一个XSD文件描述
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.dqf.com/schema/user"
xmlns:tns="http://www.dqf.com/schema/user" elementFormDefault="qualified">
<element name="user">
<complexType>
<attribute name="id" type="string"></attribute>
<attribute name="userName" type="string"></attribute>
<attribute name="email" type="string"></attribute>
</complexType>
</element>
</schema>
- 定义用来解析XSD文件中定义和组件
public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser{
protected Class 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(org.springframework.util.StringUtils.hasText(userName)){
bean.addPropertyValue("userName", userName);
}
if(org.springframework.util.StringUtils.hasText(email)){
bean.addPropertyValue("email", email);
}
}
}
- 定义一个Handler文件,将组件注册到Spring容器
public class MyNamespaceHandler extends NamespaceHandlerSupport{
@Override
public void init() {
registerBeanDefinitionParser("user", new UserBeanDefinitionParser());
}
}
- 添加Spring.handlers,spring.schemas文件
http\://www.dqf.com/schema/user=com.demo3.MyNamespaceHandler
http\://www.dqf.com/schema/user.xsd=META-INF/customtag.xsd
- 测试
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:myname="http://www.dqf.com/schema/user"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.dqf.com/schema/user
http://www.dqf.com/schema/user.xsd">
<myname:user id="testbean" userName="aaa" email="bbb"></myname:user>
<bean id="myTestBean" class="com.demo.model.MyTestBean" />
</beans>
public class App {
public static void main(String[] args) {
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("springContext.xml"));
MyTestBean testBean = (MyTestBean)bf.getBean("myTestBean");
System.out.println(testBean.getTestStr());
User test = (User) bf.getBean("testbean");
System.out.println(test.getUserName()+","+test.getEmail());
}
}
- 结果
二、自定义标签的解析
1、整体过程
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
//获取对应的命名空间
String namespaceUri = getNamespaceURI(ele);
//根据命名空间找到对应的NamespaceHandler
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
//调用NamespaceHandler进行解析
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
2、提取自定义标签处理器
@Override
public NamespaceHandler resolve(String namespaceUri) {
//获取所有已经配置的handler配置
Map<String, Object> handlerMappings = getHandlerMappings();
//根据命名空间找到对应的信息
Object handlerOrClassName = handlerMappings.get(namespaceUri);
if (handlerOrClassName == null) {
return null;
}
else if (handlerOrClassName instanceof NamespaceHandler) {
//已经做过解析的,直接从缓存中获取
return (NamespaceHandler) handlerOrClassName;
}
else {
//没有做过解析的,则返回的是类路径
String className = (String) handlerOrClassName;
try {
//利用反射将类路径转化为类
Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
}
//初始化类
NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
//调用自定义的初始化方法
namespaceHandler.init();
//记录在缓存中
handlerMappings.put(namespaceUri, namespaceHandler);
return namespaceHandler;
}
catch (ClassNotFoundException ex) {
throw new FatalBeanException("NamespaceHandler class [" + className + "] for namespace [" +
namespaceUri + "] not found", ex);
}
catch (LinkageError err) {
throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" +
namespaceUri + "]: problem with handler class file or dependent class", err);
}
}
}
3、标签解析
@Override
public final BeanDefinition parse(Element element, ParserContext parserContext) {
AbstractBeanDefinition definition = parseInternal(element, parserContext);
if (definition != null && !parserContext.isNested()) {
try {
String id = resolveId(element, definition, parserContext);
if (!StringUtils.hasText(id)) {
parserContext.getReaderContext().error(
"Id is required for element '" + parserContext.getDelegate().getLocalName(element)
+ "' when used as a top-level tag", element);
}
String[] aliases = null;
if (shouldParseNameAsAliases()) {
String name = element.getAttribute(NAME_ATTRIBUTE);
if (StringUtils.hasLength(name)) {
aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name));
}
}
BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases);
registerBeanDefinition(holder, parserContext.getRegistry());
if (shouldFireEvents()) {
BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder);
postProcessComponentDefinition(componentDefinition);
parserContext.registerComponent(componentDefinition);
}
}
catch (BeanDefinitionStoreException ex) {
parserContext.getReaderContext().error(ex.getMessage(), element);
return null;
}
}
return definition;
}