基于Spring 自定义标签实现

阅读更多
一、源码分析:
  Spring标签的定义分为默认标签和自定义标签
  Spring源代码:[DefaultBeanDefinitionDocumentReader.java]
/**
	 * Parse the elements at the root level in the document:
	 * "import", "alias", "bean".
	 * @param root the DOM root element of the document
	 */
	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		//对beans的处理
		if (delegate.isDefaultNamespace(root)) {
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					if (delegate.isDefaultNamespace(ele)) {
						//对默认标签处理
						parseDefaultElement(ele, delegate);
					}
					else {            //对自定义标签处理
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else { //对自定义标签处理
			delegate.parseCustomElement(root);
		}
	}

Spring其他集成组件如SpringMVC使用了自定义标签。
二、实现自定义标签
   步骤:
    1、创建一个需要扩展的组件。
       如:定义一个User来接受xml文件信息
        
package ppfuns;

/**
 * Created with IntelliJ IDEA.
 * User: **
 * Date: 2017/11/22
 * Time: 10:09
 * To change this template use File | Settings | File Templates.
 */
public class User {
    private String username;
    private String email;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

          

    2、定义一个XSD文件描述主键内容。
         如创建了一个user.xsd文件
        


    
        
            
            
            
        
    

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

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 ppfuns.User;

/**
 * Created with IntelliJ IDEA.
 * User: 简德群
 * Date: 2017/11/22
 * Time: 10:22
 * To change this template use File | Settings | File Templates.
 */
public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
    /**
     * Element 对应的元素User
     * @param element
     * @return
     */
    protected Class getBeanClass(Element element){
        return User.class;
    }

    /**
     * 从element元素中提取对应元素的值
     * @param element
     * @param builder
     */
    @Override
    protected void doParse(Element element, BeanDefinitionBuilder builder) {
        String username = element.getAttribute("name");
        String email = element.getAttribute("email");
        if(StringUtils.hasText(username)){
            builder.addPropertyValue("name",username);
        }
        if(StringUtils.hasText(email)){
            builder.addPropertyValue("email",email);
        }
    }
}
 

    4、创建一个handler文件,扩展自NamespaceHandlerSupport,目的是将组件注册到Spring容器中
package ppfuns.parser;

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 ppfuns.User;

/**
 * Created with IntelliJ IDEA.
 * User: 简德群
 * Date: 2017/11/22
 * Time: 10:22
 * To change this template use File | Settings | File Templates.
 */
public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
    /**
     * Element 对应的元素User
     * @param element
     * @return
     */
    protected Class getBeanClass(Element element){
        return User.class;
    }

    /**
     * 从element元素中提取对应元素的值
     * @param element
     * @param builder
     */
    @Override
    protected void doParse(Element element, BeanDefinitionBuilder builder) {
        String username = element.getAttribute("name");
        String email = element.getAttribute("email");
        if(StringUtils.hasText(username)){
            builder.addPropertyValue("name",username);
        }
        if(StringUtils.hasText(email)){
            builder.addPropertyValue("email",email);
        }
    }
}


    5、编写spring.handlers和Spring.schemas文件。这两个文件需放在resources/META-INF下
       spring.handlers文件:指定NamespaceHander位置
      
http\://www.lexueba.com/schema/user=ppfuns.parser.MyNameSpaceHandler

       spring.schemas文件:指定xsd文件映射位置
      
http\://www.lexueba.com/schema/user/user.xsd=user.xsd

   上面已经完成了对自定义标签的实现,那接下来就测试一下咯
    spring-user.xml文件定义
   



	 


    Test运行代码:
    
package ppfuns.junit;

import junit.framework.Assert;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import ppfuns.lookup.TestAbstractLookupMethod;
import ppfuns.replaceMethod.ReplacedMethodTest;

/**
 * Created with IntelliJ IDEA.
 * User: 简德群
 * Date: 2017/11/27
 * Time: 9:56
 * To change this template use File | Settings | File Templates.
 */
public class JunitTest {
  
    @Test
    public void test(){
        BeanFactory bf = new  XmlBeanFactory(new ClassPathResource("spring-user.xml"));
        ppfuns.User t1 = (ppfuns.User) bf.getBean("userBean");
        Assert.assertSame(t1,t1);
        System.out.println(t1.getUsername()+","+t1.getEmail());
    }
}

     

  说明:如想了解具体实现看《Spring源码深度解析》的第4章节

你可能感兴趣的:(bean,java,spring)