spring自定义标签使用
例如:
<nettyrpc:service id="demoAddService" interfaceName="com.wqh.rpc.services.AddCalculate" ref="calcAddService"></nettyrpc:service>
第一步:自定义xsd文件,nettyrpc.xsd,具体代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.wqh.com/nettyrpc"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
targetNamespace="http://www.wqh.com/nettyrpc"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans"/>
<xsd:element name="service">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:attribute name="interfaceName" type="xsd:string" use="required"/>
<xsd:attribute name="ref" type="xsd:string" use="required"/>
<xsd:attribute name="filter" type="xsd:string" use="optional"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>
中的name是用来定义该标签名称
中的type是用来定义该属性的格式,例如
- xsd:string 表示是一个字符串,对格式没什么要求
- xsd:id 表示该属性的值是一个id,有格式要求(例如不能以数字开头)。
- xsd:IDREF 表示该属性的值与某xsd:id属性的值对应
其他还有很多,例如decimal,integer,boolean,date,time等等
中的use是用来定义该属性的使用,例如
required 表示是为必须有该属性
prohibited 表示该属性禁止使用。
- optional 表示该属性为选择性属性
详细介绍参见:XSD属性
第二步:自定义配置文件
完成了xsd文件编写后,还需要让该文件生效,就需要在项目的resource/META-INF包里面配置2个文件spring.handlers和spring.schemas
1)spring.handlers
http\://www.wqh.com/nettyrpc=com.wqh.rpc.spring.NettyRpcNamespaceHandler
2)spring.schemas
http\://www.wqh.com/nettyrpc/nettyrpc.xsd=META-INF/nettyrpc.xsd
这样,就可以在Spring的xml配置文件中加入spring.schemas的url,省略掉其他的,在
<beans xmlns:nettyrpc="http://www.wqh.com/nettyrpc" xsi:schemaLocation="http://www.wqh.com/nettyrpc http://www.wqh.com/nettyrpc/nettyrpc.xsd">
完成这步以后,就可以在xml中写自己的标签了,例如自定义标签的namespace为service
<nettyrpc:service id="demoAddService" interfaceName="com.wqh.rpc.services.AddCalculate" ref="calcAddService"></nettyrpc:service>
第二步:自定义标签的解析
在上一步spring.handlers中,我们配置了类com.wqh.rpc.spring.NettyRpcNamespaceHandler作为解析自定义标签的类,所以namespace为service的标签,都会用这里注册的标签解析器来解析
public class NettyRpcNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("service", new NettyRpcServiceParser());
}
}
我们自定义的标签解析器NettyRpcServiceParser是要实现BeanDefinitionParser 接口的
public class NettyRpcServiceParser implements BeanDefinitionParser {
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
String interfaceName = element.getAttribute("interfaceName");
String ref = element.getAttribute("ref");
String filter = element.getAttribute("filter");
RootBeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClass(NettyRpcService.class);
beanDefinition.setLazyInit(false);
beanDefinition.getPropertyValues().addPropertyValue("interfaceName", interfaceName);
beanDefinition.getPropertyValues().addPropertyValue("ref", ref);
beanDefinition.getPropertyValues().addPropertyValue("filter", filter);
parserContext.getRegistry().registerBeanDefinition(interfaceName, beanDefinition);
return beanDefinition;
}
}
对应的BeanClass
public class NettyRpcService implements ApplicationContextAware, ApplicationListener {
private String interfaceName;
private String ref;
private String filter;
private ApplicationContext applicationContext;
@Override
public void onApplicationEvent(ApplicationEvent event) {
ServiceFilterBinder binder = new ServiceFilterBinder();
if (StringUtils.isBlank(filter) || !(applicationContext.getBean(filter) instanceof Filter)) {
binder.setObject(applicationContext.getBean(ref));
} else {
binder.setObject(applicationContext.getBean(ref));
binder.setFilter((Filter) applicationContext.getBean(filter));
}
MessageRecvExecutor.getInstance().getHandlerMap().put(interfaceName, binder);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
applicationContext.publishEvent(new ServerStartEvent(new Object()));
}
public ApplicationContext getApplicationContext() {
return applicationContext;
}
public String getFilter() {
return filter;
}
public void setFilter(String filter) {
this.filter = filter;
}
public String getRef() {
return ref;
}
public void setRef(String ref) {
this.ref = ref;
}
public String getInterfaceName() {
return interfaceName;
}
public void setInterfaceName(String interfaceName) {
this.interfaceName = interfaceName;
}
}
通过以上三步,就可以实现自己定义标签,并且在Spring容器中注入相关的bean。让我们的框架使用起来更方便(更装B)
还没有评论,来说两句吧...