1: write in front
Spring provides tags by default, our commonly used bean tags, property, constructor-arg, etc. Spring also allows us to customize tags.
2: The parsing process of the default label
Here we take the xsd
constraint file as an example to describe briefly. First, there needs to be an xsd constraint file, and then a spring.schema file is needed to describe the correspondence between the namespace and the xsd file. These are also necessary when customizing tags. Less, in addition to our custom label, we also need a parsing class, so we also need to have such a class. In spring, this class must implement the org.springframework.beans.factory.xml.NamespaceHandler
interface. In fact, we only need to inherit the org.springframework.beans.factory.xml.NamespaceHandlerSupport
abstract subclass. Let us implement these one by one 必须条件
.
3: Examples
3.1: Examples
Custom tags, realize bean
the role of tags, that is, complete the work of creating a spring bean.
3.2: Define the xsd constraint file
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://dongshi.daddy.com/schema/ok"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://dongshi.daddy.com/schema/ok"
elementFormDefault="qualified">
<!-- 定义service顶层标签,其类型是复杂类型server -->
<xsd:element name="service" type="server">
<xsd:annotation>
<xsd:documentation><![CDATA[ The service config ]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- 定义server类型可以有哪些属性 -->
<xsd:complexType name="server">
<xsd:attribute name="id" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[ The unique identifier for a bean. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="serverName" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[ The name of the bean. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:schema>
The meaning of the expression is that there can be an id attribute and a serverName attribute in the service tag. Finally, put the file in the resources
resource file directory and name the file dongshidaddy-1.0.xsd
, which will be used in subsequent configuration. Among them targetNamespace="http://dongshi.daddy.com/schema/ok"
is to set the namespace of the constraint file http://dongshi.daddy.com/schema/ok
.
3.3: Configure xsd constraint file
It needs to spring.schemas
be configured in and the file needs to be placed in a META-INF
folder under the classpath , so you need to define the folder under resources first. The definition content is as follows:
http\://dongshi.daddy.com/schema/ok/ok-1.0.xsd=./dongshidaddy-1.0.xsd
3.4: Define the class that parses custom tags
Pay attention to the implementation of the interface org.springframework.beans.factory.xml.BeanDefinitionParser
, the main code has been commented:
public class CommonNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
this.registerBeanDefinitionParser("service",
new OkServerDefinitionParser(ServerBean.class));
}
}
OkServerDefinitionParser:
public class OkServerDefinitionParser implements BeanDefinitionParser {
private final Class<?> clazz;
private static final String default_prefix = "ok-";
private static final AtomicLong COUNT = new AtomicLong(0);
public OkServerDefinitionParser(Class<?> clazz) {
this.clazz = clazz;
}
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
return parseHelper(element, parserContext, this.clazz);
}
private BeanDefinition parseHelper(Element element, ParserContext parserContext, Class<?> clazz) {
// 创建封装信息的beandefinition
RootBeanDefinition bd = new RootBeanDefinition();
// 不延迟加载
bd.setLazyInit(false);
String id = element.getAttribute("id");
if (id == null || id.isEmpty()) {
id = default_prefix + COUNT.getAndDecrement();
}
// 获取配置的serverName的值
String serverName = element.getAttribute("serverName");
// 设置class
bd.setBeanClass(clazz);
// 设置初始化方法的名称
bd.setInitMethodName("init");
// 从beandefinition中获取存储属性名称->属性值新的对象
MutablePropertyValues propertyValues = bd.getPropertyValues();
// 添加serverName属性和其值到可修改属性值对象中
propertyValues.addPropertyValue("serverName", serverName);
// 通过注册机注册BeanDefinition信息,最终会存储到一个map中,key就是id,value就是BeanDefinition
parserContext.getRegistry().registerBeanDefinition(id, bd);
// 返回创建的BeanDefinition,后续spring就会使用这个BeanDefinition对象来创建spring bean了
return bd;
}
}
ServerBean:
public class ServerBean {
private String serverName;
//init method
public void init() {
System.out.println("bean ServerBean init.");
}
@Override
public String toString() {
return "[Service]=>" + serverName;
}
public String getServerName() {
return serverName;
}
public void setServerName(String serverName) {
this.serverName = serverName;
}
}
3.5: Register the analytical class
In META-INF
case create a file spring.handlers
file, as follows:
http\://dongshi.daddy.com/schema/ok=yudaosourcecode.selfdefinetag.CommonNamespaceHandler
Means that if it is a namespace, http\://dongshi.daddy.com/schema/ok
the resolution class is usedyudaosourcecode.selfdefinetag.CommonNamespaceHandler
3.6: define xml
<?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:ok="http://dongshi.daddy.com/schema/ok"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://dongshi.daddy.com/schema/ok
http://dongshi.daddy.com/schema/ok/dongshidaddy-1.0.xsd">
<ok:service id="testServer" serverName="HelloWorldService"/>
</beans>
Among them, xmlns:ok="http://dongshi.daddy.com/schema/ok"
the namespace is defined http://dongshi.daddy.com/schema/ok
using a prefix <ok:
, and xsi:schemaLocation
the location of the constraint file is declared in.
3.7: Test code
@Test
public voidtestSelfDefineTag() {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("testselfdefinetag.xml");
ServerBean testServer = ac.getBean("testServer", ServerBean.class);
System.out.println(testServer);
}
run:
bean ServerBean init.
[Service]=>HelloWorldService
Process finished with exit code 0