基于xml schema的扩展标签
xml schema是spring 2.0版本之后引入的,在之后的2.5和3.x加入了新的元素。引入的主要动机在于:虽说spring把<bean/>中一切皆为对象,但在开发人员的角度上讲,我们要在Spring中具体化或抽象化一些东西,比如具体化单值、集合;或特定于具体应用的抽象比如AOP,事务。那不得不在spring中配置一些基础设施bean。或第三方框架支持我们都使用过spring Security框架,说实在的如果不使用security标签,我们必须为每个过滤器有一个<bean/>定义。所以我们为了方便不得不去自定义标签,xml schema将适用。
引入schema
dtd配置
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"><beans><!-- bean definitions here --></beans>
schema配置
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!-- bean definitions here --></beans>
以上配置复制粘贴就行,其中schemaLocation不是必须的,但在开发可以通过他在jar中找到spring-beans.xsd。接下来看下spring中提供的自定义标签.
util schema
主要处理集合,对象或类域。使用之前,配置schema头
<?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:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"><!-- bean definitions here --></beans>
<util:constant/>
使用之前
<bean id="..." /> </property></bean>
比较复杂的构造基本通过FactoryBean实现,FieldRetrievingFactoryBean检索类或对象的字段。
基于schema的配置
<bean id="..." name="code"><!-- target bean to be referenced by name --><bean id="testBean" scope="prototype"> <property name="age" value="10"/> <property name="spouse"> <bean value="11"/> </bean> </property></bean><!-- will result in 10, which is the value of property 'age' of bean 'testBean' --><bean id="testBean.age" name="code"><!-- target bean to be referenced by name --><bean id="testBean" scope="prototype"> <property name="age" value="10"/> <property name="spouse"> <bean value="11"/> </bean> </property></bean><!-- will result in 10, which is the value of property 'age' of bean 'testBean' --><util:property-path id="name" path="testBean.age"/>
<util:properties/>
使用之前
<!-- creates a java.util.Properties instance with values loaded from the supplied location --><bean id="jdbcConfiguration" value="classpath:com/foo/jdbc-production.properties"/></bean>
PropertiesFactoryBean实例化java.util.Properties,载入location指定Resource资源。
基于schema设置
<!-- creates a java.util.Properties instance with values loaded from the supplied location --><util:properties id="jdbcConfiguration" location="classpath:com/foo/jdbc-production.properties"/>
<util:list/>
使用之前
<!-- creates a java.util.List instance with values loaded from the supplied 'sourceList' --><bean id="emails" name="code"><!-- creates a java.util.List instance with the supplied values --><util:list id="emails" list-name="code"><!-- creates a java.util.Map instance with values loaded from the supplied 'sourceMap' --><bean id="emails" value="pechorin@hero.org"/> <entry key="raskolnikov" value="raskolnikov@slums.org"/> <entry key="stavrogin" value="stavrogin@gov.org"/> <entry key="porfiry" value="porfiry@gov.org"/> </map> </property></bean>
MapFactoryBean创建了一个Map
基于schema配置
<!-- creates a java.util.Map instance with the supplied key-value pairs --><util:map id="emails" map-value="pechorin@hero.org"/> <entry key="raskolnikov" value="raskolnikov@slums.org"/> <entry key="stavrogin" value="stavrogin@gov.org"/> <entry key="porfiry" value="porfiry@gov.org"/></util:map>
<util:set/>
使用之前
<!-- creates a java.util.Set instance with values loaded from the supplied 'sourceSet' --><bean id="emails" name="code"><util:set id="emails" set-name="code"><?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:jee="http://www.springframework.org/schema/jee" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd"><!-- bean definitions here --></beans>
<jee:jndi-lookup/> 简单
使用之前
<bean id="dataSource" value="jdbc/MyDataSource"/></bean><bean id="userDao" ref="dataSource"/></bean
基于schema配置
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/MyDataSource"/><bean id="userDao" ref="dataSource"/></bean>
<jee:jndi-lookup/> 单环境设置
使用之前
<bean id="simple" value="jdbc/MyDataSource"/> <property name="jndiEnvironment"> <props> <prop key="foo">bar</prop> </props> </property></bean>
基于schema配置
<jee:jndi-lookup id="simple" jndi-name="jdbc/MyDataSource"> <jee:environment>foo=bar</jee:environment></jee:jndi-lookup>
<jee:jndi-lookup/> 多环境设置
使用之前
<bean id="simple" value="jdbc/MyDataSource"/> <property name="jndiEnvironment"> <props> <prop key="foo">bar</prop> <prop key="ping">pong</prop> </props> </property></bean>
基于schema配置
<jee:jndi-lookup id="simple" jndi-name="jdbc/MyDataSource"> <jee:environment> foo=bar ping=pong</jee:environment></jee:jndi-lookup>
<jee:jndi-lookup/> 复杂设置
使用之前
<bean id="simple" value="jdbc/MyDataSource"/> <property name="cache" value="true"/> <property name="resourceRef" value="true"/> <property name="lookupOnStartup" value="false"/> <property name="expectedType" value="com.myapp.DefaultFoo"/> <property name="proxyInterface" value="com.myapp.Foo"/></bean>
基于schema配置
<jee:jndi-lookup id="simple" jndi-name="jdbc/MyDataSource" cache="true" resource-ref="true" lookup-on-startup="false" expected-type="com.myapp.DefaultFoo" proxy-interface="com.myapp.Foo"/>
<jee:local-slsb/> 简单
<jee:local-slsb/>配置一个本地EJB无状态会话BEAN
使用之前
<bean id="simple" value="ejb/RentalServiceBean"/> <property name="businessInterface" value="com.foo.service.RentalService"/></bean>
基于schema配置
<jee:local-slsb id="simpleSlsb" jndi-name="ejb/RentalServiceBean" business-interface="com.foo.service.RentalService"/>
<jee:local-slsb/>复杂配置
使用之前
<bean id="complexLocalEjb" value="ejb/RentalServiceBean"/> <property name="businessInterface" value="com.foo.service.RentalService"/> <property name="cacheHome" value="true"/> <property name="lookupHomeOnStartup" value="true"/> <property name="resourceRef" value="true"/></bean>
基于schema配置
<jee:local-slsb id="complexLocalEjb" jndi-name="ejb/RentalServiceBean" business-interface="com.foo.service.RentalService" cache-home="true" lookup-home-on-startup="true" resource-ref="true">
<jee:remote-slsb/>
<jee:remote-slsb/>配置一个远程EJB无状态会话BEAN
使用之前
<bean id="complexRemoteEjb" value="ejb/MyRemoteBean"/> <property name="businessInterface" value="com.foo.service.RentalService"/> <property name="cacheHome" value="true"/> <property name="lookupHomeOnStartup" value="true"/> <property name="resourceRef" value="true"/> <property name="homeInterface" value="com.foo.service.RentalService"/> <property name="refreshHomeOnConnectFailure" value="true"/></bean>
基于schema配置
<jee:remote-slsb id="complexRemoteEjb" jndi-name="ejb/MyRemoteBean" business-interface="com.foo.service.RentalService" cache-home="true" lookup-home-on-startup="true" resource-ref="true" home-interface="com.foo.service.RentalService" refresh-home-on-connect-failure="true">
lang schema
lang标签用来暴露用脚本语言写的bean,比如Jruby,Groovy,Beanshell
<?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:lang="http://www.springframework.org/schema/lang" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd"><!-- bean definitions here --></beans>
jms schema
处理JMS相关的BEAN
<?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:jms="http://www.springframework.org/schema/jms" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms.xsd"><!-- bean definitions here --></beans>
tx (transaction) schema
事务处理
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!-- bean definitions here --></beans>
aop schema
<?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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!-- bean definitions here --></beans>
context schema
spring 2.5之后才有
<?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- bean definitions here --></beans>
<property-placeholder/>
根据指定资源文件(spring resource)激活${},用 PropertyPlaceholderConfigurer实现
<annotation-config/>
激活侦测配置bean上的注解
@Required ,@Autowired,@PreDestroy , @Resource , @PersistenceContext,@PersistenceUnit
<component-scan/> 自动侦测类,注解
<load-time-weaver/> 使用AspectJ
<spring-configured/> 使用AspectJ用在领域对象
<mbean-export/>导出Mbean
jdbc schema
配置内嵌数据库和初始化内嵌数据库
<?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:jdbc="http://www.springframework.org/schema/jdbc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd"><!-- bean definitions here --></beans>
<jdbc:embedded-database/>内嵌数据库支持 HSQL, H2, Derby
<jdbc:embedded-database id="dataSource"> <jdbc:script location="classpath:schema.sql"/> <jdbc:script location="classpath:test-data.sql"/> </jdbc:embedded-database>
<jdbc:initialize-database />
初始化内嵌数据库
<jdbc:initialize-database data-source="dataSource"> <jdbc:script location="classpath:com/foo/sql/db-schema.sql"/> <jdbc:script location="classpath:com/foo/sql/db-test-data.sql"/></jdbc:initialize-database>
自定义扩展标签
- 编写schema实现解析标签的NamespaceHandler实现BeanDefinitionParser 钩入以上实现配置到Spring中
实现bean定义如下
<myns:dateformat id="dateFormat" pattern="yyyy-MM-dd HH:mm" lenient="true"/>
编写schema
<!-- myns.xsd (inside package org/springframework/samples/xml) --><?xml version="1.0" encoding="UTF-8"?><xsd:schema xmlns="http://www.mycompany.com/schema/myns" 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="dateformat"> <xsd:complexType> <xsd:complexContent> <xsd:extension base="beans:identifiedType"> <xsd:attribute name="lenient" type="xsd:boolean"/> <xsd:attribute name="pattern" type="xsd:string" use="required"/> </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:element></xsd:schema>
2.编写NamespaceHandler
NamespaceHandler 接口有三个方法
init():第一次被使用时调用,注册BeanDefinitionParser
BeanDefinition parse(Element, ParserContext):作为顶级元素时被调用
BeanDefinitionHolder decorate(Node, BeanDefinitionHolder, ParserContext) :作为内嵌bean或不同namespace时被调用
package org.springframework.samples.xml;import org.springframework.beans.factory.xml.NamespaceHandlerSupport;public class MyNamespaceHandler extends NamespaceHandlerSupport { public void init() { registerBeanDefinitionParser("dateformat", new SimpleDateFormatBeanDefinitionParser()); }}
3.编写BeanDefinitionParser
package org.springframework.samples.xml;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 java.text.SimpleDateFormat;public class SimpleDateFormatBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { protected Class getBeanClass(Element element) { return SimpleDateFormat.class; } protected void doParse(Element element, BeanDefinitionBuilder bean) { // this will never be null since the schema explicitly requires that a value be supplied String pattern = element.getAttribute("pattern"); bean.addConstructorArg(pattern); // this however is an optional property String lenient = element.getAttribute("lenient"); if (StringUtils.hasText(lenient)) { bean.addPropertyValue("lenient", Boolean.valueOf(lenient)); } }}
4.钩入配置
META-INF/spring.handlers指定命名空间处理器
http\://www.mycompany.com/schema/myns=org.springframework.samples.xml.MyNamespaceHandler
META-INF/spring.schemas指定schema路径,用于schema验证(xsd放在class路径下)
http\://www.mycompany.com/schema/myns/myns.xsd=org/springframework/samples/xml/myns.xsd
5.使用扩展标签
<?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.xsdhttp://www.mycompany.com/schema/myns http://www.mycompany.com/schema/myns/myns.xsd"> <!-- as a top-level bean --> <myns:dateformat id="defaultDateFormat" pattern="yyyy-MM-dd HH:mm" lenient="true"/> <bean id="jobDetailTemplate" abstract="true"> <property name="dateFormat"> <!-- as an inner bean --> <myns:dateformat pattern="HH:mm MM-dd-yyyy"/> </property> </bean></beans>