导航

Spring框架的XML扩展特性

Posted on 2016-10-20 13:46  eastson  阅读(1010)  评论(0编辑  收藏  举报

Spring框架从2.0版本开始,提供了基于Schema风格的XML扩展机制,允许开发者扩展spring配置文件。现在我们来看下怎么实现这个功能,可以参考spring帮助文档中的《Extensible XML authoring》。

我们知道如果在需要在spring.xml中配置数据源,需要进行如下的配置:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">       
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />      
    <property name="url" value="jdbc:mysql://localhost:3309/sampledb" />      
    <property name="username" value="root" />      
    <property name="password" value="1234" />      
</bean>

这种方式配置虽然也比较简单,但是有一个缺点:使用<property>标签不够明显,不如元素属性那么直接。现在我们希望在spring.xml中做如下的配置,就能够完成数据源的配置。

<myns:datasource id="myDataSourcce" 
    driverClassName="com.mysql.jdbc.Driver"
    url="jdbc:mysql://localhost:3309/demodb" 
    userName="root" 
    password="root" />

如果让spring能够解析这个标签,需要4步。

1、提供一个xsd文件,负责对xml的标签<datasource>进行校验。

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.aty.com/schema/aty" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:beans="http://www.springframework.org/schema/beans"
    targetNamespace="http://www.mycompany.com/schema/myns"
    elementFormDefault="qualified"
    attributeFormDefault="unqualified">

    <xsd:import namespace="http://www.springframework.org/schema/beans" />

    <xsd:element name="datasource">
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="beans:identifiedType">
                    <xsd:attribute name="driverClassName" type="xsd:string" use="required" />
                    <xsd:attribute name="url" type="xsd:string" use="required" />
                    <xsd:attribute name="username" type="xsd:string" use="required" />
                    <xsd:attribute name="password" type="xsd:string" use="required" />
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

2、定义一个BeanDefinitionParser负责解析xml,并将必要的信息放入spring中。

package net.mingyang.spring_extensible_xml;

import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.w3c.dom.Element;

public class DatasourceBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

    protected Class getBeanClass(Element element) {
        return BasicDataSource.class;
    }

    protected void doParse(Element element, BeanDefinitionBuilder bean) {
        String driverClassName = element.getAttribute("driverClassName");
        bean.addPropertyValue("driverClassName", driverClassName);

        String url = element.getAttribute("url");
        bean.addPropertyValue("url", url);

        String username = element.getAttribute("username");
        bean.addPropertyValue("username", username);

        String password = element.getAttribute("password");
        bean.addPropertyValue("password", password);
    }
}

3、定义个NamespaceHandler, 由sping框架的调用入口。

package net.mingyang.spring_extensible_xml;

import org.springframework.beans.factory.xml.NamespaceHandlerSupport;

public class DatasourceNamespaceHandlerSupport extends NamespaceHandlerSupport
{
    public void init()
    {
        registerBeanDefinitionParser("datasource",
                new DatasourceBeanDefinitionParser());
    }
}

4、配置schema和handler。我们通过一些配置文件来告知Spring,它们就是spring.handlers和spring.schemas,它们放在META-INF目录中。
spring.handlers内容如下: 

http\://www.mycompany.com/schema/myns=net.mingyang.spring_extensible_xml.DatasourceNamespaceHandlerSupport

spring.schemas内容如下:

http\://www.mycompany.com/schema/myns/myns.xsd=META-INF/myns.xsd

OK,到这里Spring需要的所有定义就完了。

测试类:

package net.mingyang.spring_extensible_xml;

import javax.sql.DataSource;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class DatasourceXmlTest
{
    public static void main(String[] args)
    {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                "spring.xml");
        DataSource ds = (DataSource) context.getBean("myDataSourcce");
        System.out.println(ds);
    }
}

spring.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:myns="http://www.mycompany.com/schema/myns"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd 
        http://www.mycompany.com/schema/myns
        http://www.mycompany.com/schema/myns/myns.xsd">
        
    <myns:datasource id="myDataSourcce" 
        driverClassName="com.mysql.jdbc.Driver"
        url="jdbc:mysql://localhost:3309/demodb" 
        username="root" 
        password="root" />
    
</beans>

文件:spring-extensible-xml.rar