bean
标签,自定义标签如:aop
、tx
(关于事物的)、dubbo
(rpc框架的)。在一些复杂的业务场景下,普通bean无法满足需求;spring提供了可扩展Schema的支持,只需要我们实现部分逻辑就可以为我们解析自定义标签;spring自定义标签用于配置较为复杂或者需要丰富的控制的时候。package com.zzq.provider.customtag.pojo;
public class Dubbo {
/*spring beanName*/
private String id;
/*消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样*/
private String name;
/*使用zookeeper注册中心暴露服务地址 */
private String address;
/*使用zookeeper注册中心暴露服务地址*/
private String protocol;
/*生成远程服务代理,可以像使用本地bean一样使用demoService*/
private String basePackage;
/*消费者调用超时设置为10秒*/
private String timeout;
/*端口*/
private String port;
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public String getBasePackage() {
return basePackage;
}
public void setBasePackage(String basePackage) {
this.basePackage = basePackage;
}
public String getTimeout() {
return timeout;
}
public void setTimeout(String timeout) {
this.timeout = timeout;
}
}
public class DubboBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
// element对应的类
@Override
protected Class> getBeanClass(Element element) {
return Dubbo.class;
}
// 从element中解析并提取对应的元素
/*@Override
protected void doParse(Element element, BeanDefinitionBuilder builder) {
String id = element.getAttribute("id");
String address = element.getAttribute("address");
String name = element.getAttribute("name");
String protocol = element.getAttribute("protocol");
String basePackage = element.getAttribute("basePackage");
String timeout = element.getAttribute("timeout");
String port = element.getAttribute("port");
if (StringUtils.hasText(id)) {
builder.addPropertyValue("id", id);
}
if (StringUtils.hasText(address)) {
builder.addPropertyValue("address", address);
}
if (StringUtils.hasText(name)) {
builder.addPropertyValue("name", name);
}
if (StringUtils.hasText(protocol)) {
builder.addPropertyValue("protocol", protocol);
}
if (StringUtils.hasText(basePackage)) {
builder.addPropertyValue("basePackage", basePackage);
}
if (StringUtils.hasText(timeout)) {
builder.addPropertyValue("timeout", timeout);
}
if (StringUtils.hasText(port)) {
builder.addPropertyValue("port", port);
}
System.out.println("id :" + id +" name : " +name +" address :" +address);
}*/
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
String id = element.getAttribute("id");
String address = element.getAttribute("address");
String name = element.getAttribute("name");
String protocol = element.getAttribute("protocol");
String basePackage = element.getAttribute("basePackage");
String timeout = element.getAttribute("timeout");
String port = element.getAttribute("port");
if (StringUtils.hasText(id)) {
builder.addPropertyValue("id", id);
}
if (StringUtils.hasText(address)) {
builder.addPropertyValue("address", address);
}
if (StringUtils.hasText(name)) {
builder.addPropertyValue("name", name);
}
if (StringUtils.hasText(protocol)) {
builder.addPropertyValue("protocol", protocol);
}
if (StringUtils.hasText(basePackage)) {
builder.addPropertyValue("basePackage", basePackage);
}
if (StringUtils.hasText(timeout)) {
builder.addPropertyValue("timeout", timeout);
}
if (StringUtils.hasText(port)) {
builder.addPropertyValue("port", port);
}
System.out.println("id :" + id +" name : " +name +" address :" +address);
}
}
package com.zzq.provider.customtag.handler;
import com.zzq.provider.customtag.parser.DubboBeanDefinitionParser;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class DubboNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("dubbo",new DubboBeanDefinitionParser());
}
}
(1) spring.handlers
http\://www.lexueba.com/schema/dubbo=com.zzq.provider.customtag.handler.DubboNamespaceHandler
(2) spring.schemas
http\://www.lexueba.com/schema/dubbo.xsd=META-INF/Spring-dubbo.xsd
然后在启动时入口的配置文件导入即可:
DubboNamespaceHandler
这种public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
// 获取对应命名空间
String namespaceUri = getNamespaceURI(ele);
// 例如namespaceUri为http://www.springframework.org/schema/aop, 所以得到的是 AopNamespaceHandler
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));
}
public NamespaceHandler resolve(String namespaceUri) {
Map 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);
}
}
}
private Map getHandlerMappings() {
if (this.handlerMappings == null) {
synchronized (this) {
if (this.handlerMappings == null) {
try {
//载入全部项目的META-INF/spring.handlers(aop项目beans项目等等)配置文件得到对应关系如http://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler
Properties mappings =
PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
if (logger.isDebugEnabled()) {
logger.debug("Loaded NamespaceHandler mappings: " + mappings);
}
Map handlerMappings = new ConcurrentHashMap(mappings.size());
CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
this.handlerMappings = handlerMappings;
}
catch (IOException ex) {
throw new IllegalStateException(
"Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex);
}
}
}
}
return this.handlerMappings;
}
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
// 获取元素名称 中的dubbo 此时localName为dubbo
String localName = parserContext.getDelegate().getLocalName(element);
// 此时根据localName为dubbo找解析器 就是DubboBeanDefinitionParser
BeanDefinitionParser parser = this.parsers.get(localName);
if (parser == null) {
parserContext.getReaderContext().fatal(
"Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
}
return parser;
}
// 重写这个也行就看您需不需要parserContext对象了
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
//此处调用具体的实现类
doParse(element, builder);
}