zoukankan      html  css  js  c++  java
  • Spring自定义标签的实现

    首先 简单写下 spring xml解析的过程

     通过一段简单的 调用spring代码开始

    public static void main(String[] args) {
    		ApplicationContext app = new ClassPathXmlApplicationContext("classpath:/applicationContext.xml");
    		User user = (User) app.getBean("user");
    		System.out.println(user.toString());
    	}
     可以看出,简单使用spring的时候首先是要加载 xml文件,这里就涉及到 xml的解析成Beandifinition的过程,简单说下步骤

     (1)使用classloader加载器加载xml文件,转换成 Resource对象

     (2)经过转码和一系列操作转成 InputSource对象

     (3)经过 xml validate验证,判断头信息是 dtd 还是 xsd ,进而用不同解析器解析

     (4)根据解析器解析最终都会转换成 w3c的Document对象

    (5)获取Document的所有子节点,将每一个子节点都转换成Beandifinition对象

    (6)在将每一个节点转换成 BeanDifition对象时设计到 是否是自定义节点还是Spring默认节点,有两种不同的解析方法

     那么spring默认节点有哪些: import、alias、bean、beans

    对于自定义标签的解析过程和spring默认节点的区别是对于自定义的需要指定xsd和schema的位置,进而找到解析器和

    解析类,步骤如下:

     (6.1)通过getNamespaceURI(),获取标签的命名空间uri

      (6.2)加载spring默认指定下的配置文件,META-INF/spring.handlers,这个文件里有namespaceuri与解析

        器的对应关系,比如

     

    (6.3)解析标签,返回标签的localName;比如有标签 <lonely:user></lonely:user>,那么先获取到user

    (6.4)在解析器中的init方法中找到 指定 localName对应的解析类,比如


    (6.5)调用指定localName对应的解析类的parse方法完成标签的解析即可

    至此,xml的解析大致过程如上,下面开始实现 自定义标签的解析

    自定义标签解析实现步骤如下:

     (1)编写实体类用户xsd文件描述内容

    (2)编写xsd文件描述组建内容

    (3)创建一个类,实现BeanDefinitionParse接口,用于标签的解析

    (4)创建一个类,继承 NamespaceHandlerSupport,用于将组件注册到spring容器中

    (5)编写 Spring.handles 和 Spring.schemas文件,默认在工程的 /META-INF/文件夹下

    (6)创建测试文件,进行测试

    实现

     (1)新建maven项目,pom文件如下

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    	<groupId>com.lonely</groupId>
    	<artifactId>customlabel</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    
    
    	<properties>
    		<spring.version>4.3.12.RELEASE</spring.version>
    		<junit.version>4.12</junit.version>
    	</properties>
    
    	<dependencies>
    
    		<!-- Spring mvc web依赖 -->
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-webmvc</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    
    		<!-- Spring jdbc 事务控制模块 -->
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-jdbc</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    
    		<!-- Spring aspects 有关切面模块 -->
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-aspects</artifactId>
    			<version>4.3.12.RELEASE</version>
    		</dependency>
    
    		<!-- spring test 测试模块 -->
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-test</artifactId>
    			<version>${spring.version}</version>
    			<scope>test</scope>
    		</dependency>
    
    
    		<!-- junit -->
    		<dependency>
    			<groupId>junit</groupId>
    			<artifactId>junit</artifactId>
    			<version>${junit.version}</version>
    			<scope>test</scope>
    		</dependency>
    
    	</dependencies>
    
    
    	<build>
    		<plugins>
    			<!-- java编译插件 -->
    			<plugin>
    				<groupId>org.apache.maven.plugins</groupId>
    				<artifactId>maven-compiler-plugin</artifactId>
    				<configuration>
    					<source>1.8</source>
    					<target>1.8</target>
    					<encoding>UTF-8</encoding>
    				</configuration>
    			</plugin>
    		</plugins>
    	</build>
    </project>

     (2)编写User实体类

    package com.lonely.model;
    
    public class User {
    
    	private String id;
    	private String name;
    	private String age;
    	private String height;
    
    	@Override
    	public String toString() {
    		return "User [name=" + name + ", age=" + age + ", height=" + height + "]";
    	}
    
    	public String getId() {
    		return id;
    	}
    
    	public void setId(String id) {
    		this.id = id;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public String getAge() {
    		return age;
    	}
    
    	public void setAge(String age) {
    		this.age = age;
    	}
    
    	public String getHeight() {
    		return height;
    	}
    
    	public void setHeight(String height) {
    		this.height = height;
    	}
    
    	public User() {
    		// TODO Auto-generated constructor stub
    	}
    
    }
     (3)编写 lonely.xsd文件,放在resources目录下

    <?xml version="1.0" encoding="UTF-8"?>
    <xsd:schema 
        xmlns="http://jewel.com/schema/jewel" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        targetNamespace="http://jewel.com/schema/jewel" 
        elementFormDefault="qualified"
        attributeFormDefault="unqualified">
    
    
        <xsd:element name="user">
            <xsd:complexType>
                <xsd:attribute name="id" type="xsd:string"></xsd:attribute>
                <xsd:attribute name="name" type="xsd:string"></xsd:attribute>
                <xsd:attribute name="age" type="xsd:string"></xsd:attribute>
                <xsd:attribute name="height" type="xsd:string"></xsd:attribute>
            </xsd:complexType>
        </xsd:element>
        
    </xsd:schema> 
    (4) 编写 一个 UserParse类,用来解析标签,继承 AbstractSingleBeanDefinitionParser 类

    package com.lonely.parse;
    
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
    import org.springframework.util.StringUtils;
    import org.w3c.dom.Element;
    
    import com.lonely.model.User;
    
    public class UserParse extends AbstractSingleBeanDefinitionParser {
    
    	@Override
    	protected void doParse(Element element, BeanDefinitionBuilder builder) {
    		// 从元素中获取内容
    		String name = element.getAttribute("name");
    		String age = element.getAttribute("age");
    		String height = element.getAttribute("height");
    		// 将元素放入到 builder中
    		if (StringUtils.hasText(name)) {
    			builder.addPropertyValue("name", name);
    		}
    		if (StringUtils.hasText(age)) {
    			builder.addPropertyValue("age", age);
    		}
    		if (StringUtils.hasText(height)) {
    			builder.addPropertyValue("height", height);
    		}
    	}
    
    	/**
    	 * 返回元素对应的类
    	 */
    	@Override
    	protected Class<?> getBeanClass(Element element) {
    		return User.class;
    	}
    
    }
    
    (5)编写一个UserNamespaceHandler类,用于组件的注册

    package com.lonely.handlers;
    
    import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
    
    import com.lonely.parse.UserParse;
    
    public class UserNamespaceHandler extends NamespaceHandlerSupport {
    
    	@Override
    	public void init() {
    		registerBeanDefinitionParser("user", new UserParse());
    	}
    }
    

    (6)编写Spring.handler和Spring.schemas文件,放在 META-INF目录下

    Spring.handler

    http://jewel.com/schema/jewel=com.lonely.handlers.UserNamespaceHandler
     Spring.schemas

    http://jewel.com/schema/jewel.xsd=lonely.xsd

    (7)编写测试xml, spring-test.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:lonely="http://jewel.com/schema/jewel"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    	http://jewel.com/schema/jewel http://jewel.com/schema/jewel.xsd">
    
    	<lonely:user id="user" name="dugu" age="24" height="180"></lonely:user>
    
    </beans>
    

     (8)编写测试类 Test1

    package com.lonely.test;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.lonely.model.User;
    
    public class Test1 {
    
    	public static void main(String[] args) {
    		ApplicationContext app = new ClassPathXmlApplicationContext("classpath:/spring-test.xml");
    		User user = (User) app.getBean("user");
    		System.out.println(user.toString());
    	}
    
    }
    
     测试结果如下,可以看出 已经解析了自定义标签,并成功获取




     最后,展示整个项目结构












  • 相关阅读:
    Android开发学习之路--UI之简单聊天界面
    Android开发学习之路--UI之ListView
    Android开发学习之路--UI之自定义布局和控件
    Android开发学习之路--UI之基本布局
    Android开发学习之路--UI之初体验
    Android开发学习之路--Activity之四种启动模式
    Android开发学习之路--Activity之生命周期
    初探linux子系统集之i2c子系统(二)
    deque双端队列容器
    multimap多重映照容器
  • 原文地址:https://www.cnblogs.com/duguxiaobiao/p/9128798.html
Copyright © 2011-2022 走看看