Spring bean自定义标签解析注册原理

Spring 容器的基本实现原理

1概述

在上一篇文章中讲到Spring通过实现接口BeanDefinitionDocumentReader的DefaultBeanDefinitionDocumentReader类对Document进行解析,并使用BeanDefinitionParserDelegate对Element进行解析。

解析自定义标签实现

@Nullable
	public BeanDefinition parseCustomElement(Element ele) {
		return parseCustomElement(ele, null);
	}

	@Nullable
	public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
		String namespaceUri = getNamespaceURI(ele);
		if (namespaceUri == null) {
			return null;
		}
		// 处理NamespaceHandler,并调用NamespaceHandler的init方法
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
		if (handler == null) {
			error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
			return null;
		}
		// 获取解析器,解析标签
		return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
	}

处理NamespaceHandler,并调用NamespaceHandler的init方法

@Override
	@Nullable
	public NamespaceHandler resolve(String namespaceUri) {
		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("Could not find NamespaceHandler class [" + className +
						"] for namespace [" + namespaceUri + "]", ex);
			}
			catch (LinkageError err) {
				throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" +
						className + "] for namespace [" + namespaceUri + "]", err);
			}
		}
	}

获取解析器,解析标签

@Override
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		return findParserForElement(element, parserContext).parse(element, parserContext);
	}

2 自定义标签实现

2.1 主要类:

AbstractSingleBeanDefinitionParser :继承自BeanDefinitionParser接口,用于对XSD解析
NamespaceHandlerSupport:用于注册组件

2.2 创建自定义标签流程:

  1. 创建一个需要扩展的组件
  2. 定义一个XSD文件描述组件内容
  3. 创建一个文件,实现BeanDefinitionParser接口,用来解析XSD文件中的定义和组件定义
  4. 创建一个Handler文件,扩展NamespaceHandlerSupport,目的是将组件注册到Spring容器中
  5. 编写Spring.handlers和Spring.schemas文件

2.3 实现自定义标签:

(1) 首先我们定义一个普通的POJO

package com.gz.spring.customElement;

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) 定义一个XSD文件描述内容

<?xml version="1.0" encoding="UTF-8"?>    
<schema xmlns="http://www.w3.org/2001/XMLSchema"    
    xmlns:tns="http://www.gz.com/schema/user" 
    targetNamespace="http://www.gz.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) 创建一个文件,实现BeanDefinitionParser接口,用来解析XSD文件中的定义和组件定义

package com.gz.spring.customElement;

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 {    
    @Override    
    protected Class<?> getBeanClass(Element element) {    
        return User.class;    
    }    
    @Override    
    protected void doParse(Element element, BeanDefinitionBuilder builder) {    
        String userName=element.getAttribute("userName");    
        String email=element.getAttribute("email");    
        if(StringUtils.hasText(userName)){    
            builder.addPropertyValue("userName", userName);    
        }    
        if(StringUtils.hasText(email)){    
            builder.addPropertyValue("email", email);    
        }    
    }    
}  

(4) 创建一个Handler文件,扩展NamespaceHandlerSupport,目的是将组件注册到Spring容器中。

package com.gz.spring.customElement;

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

public class MyUserNamespaceHandler extends NamespaceHandlerSupport {

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

(5) 编写spring.handlers和spring.schemas文件,默认位置在工程/META-INF/文件下

spring.handlers:

http\://www.gz.com/schema/user=com.gz.spring.customElement.MyUserNamespaceHandler

spring.schemas:

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

Spring bean默认标签解析注册原理

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值