custom tags for spring

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 xsdconstraint 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.NamespaceHandlerinterface. In fact, we only need to inherit the org.springframework.beans.factory.xml.NamespaceHandlerSupportabstract subclass. Let us implement these one by one 必须条件.

3: Examples

3.1: Examples

Custom tags, realize beanthe 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 resourcesresource 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.schemasbe configured in and the file needs to be placed in a META-INFfolder 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-INFcase create a file spring.handlersfile, as follows:

http\://dongshi.daddy.com/schema/ok=yudaosourcecode.selfdefinetag.CommonNamespaceHandler

Means that if it is a namespace, http\://dongshi.daddy.com/schema/okthe 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/okusing a prefix <ok:, and xsi:schemaLocationthe 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

Guess you like

Origin blog.csdn.net/wang0907/article/details/114408134