Spring——使用自定义标签

Posted Mr.袋鼠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring——使用自定义标签相关的知识,希望对你有一定的参考价值。

文章内容参考了《Spring源码深度解析》一书。自己照着书中内容做了一遍,不懂的地方以及采坑的地方会在文中记录。

推荐一篇post,关于Spring配置文件的命名空间:

https://www.cnblogs.com/gonjan-blog/p/6637106.html

 

我们暂时只是知道使用Spring的常规标签,加个bean,事务,Aop等等。随着满足业务的需求,同时降低程序员的工作量,我们有时需要自己定制一些标签。话补多少,下面进入主题。

 

自定义标签的使用

扩展Spring自定义标签大致需要如下几步:(把大象装冰箱,需要三步,开门,放,关门。。。)

1.创建需要扩展的组件

2.定义XSD文件描述组件内容

3.创建一个文件,实现BeanDefinitionParser接口,用来解析XSD文件中的定义和组件定义

4.创建Handler文件,扩展字NamespaceHandlerSupport,目的是将组件注册到Spring容器

5.编写Spring.handlers和Spring.schemas文件

上述,五点看完了,我最开始时一头雾水,这是什么啊?别着急,跟哥往下走。下面有好东西,保证不打晕你。

 

例子:

1.创建POJO,接收配置文件

 1 package test.customtag;
 2 
 3 public class User {
 4     private String userName;
 5     public String getUserName() {
 6         return userName;
 7     }
 8     public void setUserName(String userName) {
 9         this.userName = userName;
10     }
11     private String email;
12     public String getEmail() {
13         return email;
14     }
15     public void setEmail(String email) {
16         this.email = email;
17     }
18 }

2.定义一个XSD文件描述组件内容

src/main/resources/META-INF/user.xsd

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/schema/user" xmlns:tns="http://www.example.org/schema/user" elementFormDefault="qualified">
 3     <element name="user2">
 4         <complexType>
 5             <attribute name ="id" type = "string"/>
 6             <attribute name ="userName" type = "string"/>
 7             <attribute name ="email" type = "string"/>
 8         </complexType>
 9     </element>
10 </schema>

描述了一个targetNamespace,并且创建了一个element user2。里面有三个attribute。主要是为了验证Spring配置文件中的自定义格式。再进一步解释,就是,Spring位置文件中使用的user2自定义标签中,属性只能是上面的三种,有其他的属性的话,就会报错。

网上有人说element complexType等等这些标签要用XSD开头的标签,但是我这里没有用也能成功的执行,我猜测可能是spring的版本问题。(我这个猜测没有依据)

大家对这个XSD可能会有疑问,不要担心。推荐一篇post,里面讲解的很好,地址放在文章开头那里。

3.创建文件,实现BeanDefinitionParser接口,用来解析XSD文件中的定义和组件定义

 1 package test.customtag;
 2 
 3 
 4 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
 5 import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
 6 import org.springframework.util.StringUtils;
 7 import org.w3c.dom.Element;
 8 
 9 public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
10 
11     @SuppressWarnings("rawtypes")
12     protected Class getBeanClass(Element element) {
13         return User.class;
14     }
15     
16     protected void doParse(Element element, BeanDefinitionBuilder bean) {
17         String userName = element.getAttribute("userName");
18         String email = element.getAttribute("email");
19         if (StringUtils.hasText(userName)) {
20             bean.addPropertyValue("userName", userName);
21         }
22         if (StringUtils.hasText(email)){
23             bean.addPropertyValue("email", email);
24         } 
25         
26     }
27 }

上文,虽说是继承了AbstractSingleBeanDefinitionParser ,但根本上来说,是实现了BeanDefinitionParser接口。

4.创建Handler文件,扩展自NamespaceHandlerSupport,目的是将组件注册到Spring容器中。

 1 package test.customtag;
 2 
 3 import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
 4 
 5 public class MyNamespaceHandler extends NamespaceHandlerSupport {
 6 
 7     public void init() {
 8 
 9         registerBeanDefinitionParser("user2", new UserBeanDefinitionParser());
10     }
11 
12 }

5.编写Spring.handlers和Spring.schemas文件

路径:src/main/resources/META-INF/Spring.handlers

1 http\\://www.example.org/schema/user=test.customtag.MyNamespaceHandler

路径:src/main/resources/META-INF/Spring.schemas

1 http\\://www.example.org/schema/user.xsd=META-INF/user.xsd

\\ 是转义字符的概念。

6.创建测试配置文件

路径:src/main/resources/test.xml

1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4     xmlns:myname2="http://www.example.org/schema/user"
5     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
6     http://www.example.org/schema/user http://www.example.org/schema/user.xsd">
7     
8     <myname2:user2 id = "testbean" userName = "lee" email = "bbb"/>
9 </beans>

在第4行这里引入了myname2对应的命名空间,它会到第六行(http://www.example.org/schema/user.xsd)找到对应XSD文件进行check。第六行的user.xsd文件的位置,到步骤5里的Spring.schemas里去参照。

在这里说明一下自己遇到的疑问:第八行,自己eclipse报了红叉,信息如下:

Multiple annotations found at this line:
    - cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element \'myname2:user2\'.
    - schema_reference.4: Failed to read schema document \'http://www.example.org/schema/user.xsd\', because 1) could not find the
     document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.

但是,我没有解决它,直接执行第6步的代码,最后成功执行了,搞不懂原因。

6.测试。

 1 package test.customtag;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 
 6 public class Tst {    
 7     public static void main(String[] args) {    
 8         ApplicationContext beans=new ClassPathXmlApplicationContext("classpath:test.xml");    
 9         User user=(User)beans.getBean("testbean");    
10         System.out.println("username:"+user.getUserName()+"  "+"email:"+user.getEmail());    
11     }    
12 }   

 

文章记录的不是特别的详细,有一些知识点没有全面的记录。但是,跟着一步步做,Spring自定义标签的实现,应该是没有问题了。稍后,有时间,会记录Sping源码中,关于自定义标签解析的部分。与君共勉。

 

以上是关于Spring——使用自定义标签的主要内容,如果未能解决你的问题,请参考以下文章

为片段制作自定义列表视图?

Spring自定义标签

Spring 自定义标签配置

spring源码-自定义标签-4

聊聊自定义SPI如何使用自定义标签注入到spring容器中

Android TabLayout ViewPager 不会在 backstack 上膨胀标签片段