zoukankan      html  css  js  c++  java
  • 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源码中,关于自定义标签解析的部分。与君共勉。

  • 相关阅读:
    360安全桌面的屏保图片在哪个目录下?
    IntelliJ 注解@Slf4j后找不到log问题解决
    运行springboot项目报错:Field userMapper in XX required a bean of type 'xx' that could not be found.
    springsecurity
    Error creating bean with name 'sqlSessionFactory' defined in class path resource [config/spring/applicationContext.xml]: Invocation of init method failed;
    idea热部署
    数据结构导论 三 线性表-顺序存储
    数据结构导论 二 时空性
    树莓派安装、卸载、更新软件
    数据结构导论第一章
  • 原文地址:https://www.cnblogs.com/lihao007/p/8455916.html
Copyright © 2011-2022 走看看