1 Overview
XBean是Apache Geronimo的子项目,目标是像Eclipse IDE那样,用于创建基于插件的服务器(跟Geronimo GBean的目标有些重合)。从现状来看,XBean更多地被用于简化Spring 配置。例如,Apache ActiveMQ的配置基于XBean。
2 Custom namespace
最简单的custom namespace是java://加上全路径包名的形式,以下是个简单的例子:
package com.versus.misc.xbean; import java.math.BigDecimal; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; public class Product { private String name; private BigDecimal price; public String toString() { return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) .append("name", name) .append("price", price).toString(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public BigDecimal getPrice() { return price; } public void setPrice(BigDecimal price) { this.price = price; } }
以下是配置文件xbean.xml的内容:
<beans xmlns:p="java://com.versus.misc.xbean"> <p:Product id="product" name="USD/JPY" price="100.00"/> </beans>
以下是测试用的test case:
package com.versus.misc.xbean; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import java.math.BigDecimal; import org.apache.xbean.spring.context.ClassPathXmlApplicationContext; import org.junit.Test; public class XBeanTest { @Test public void test() { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:com/versus/misc/xbean/xbean.xml"); Product product = (Product)context.getBean("product"); assertNotNull(product); assertEquals("USD/JPY", product.getName()); assertEquals(new BigDecimal("100.00"), product.getPrice()); } }
以上的例子中,custom namespace是java://com.versus.misc.xbean;Product是定义在com.versus.misc.xbean包中的一个类;Product类的成员变量都被映射成XML的属性。需要注意的是,必须使用org.xbean.spring.context.ClassPathXmlApplicationContext,而不是Spring自带的ApplicationContext。
3 Custom mapping
在之前的例子中,如果给Product类增加一个名为id的int型成员变量,那么为了避免和标准Spring属性的冲突,应该使用custom mapping。首先要在META-INF/services/org/apache/xbean/spring/目录下建立一个名为$namespace的属性文件。例如,如果namespace是http://xbean.versus.com/product,那么需要建立META-INF/services/org/apache/xbean/spring/http/xbean.versus.com/product文件,其内容如下:
package = com.versus.misc.xbean product = com.versus.misc.xbean.Product product.alias.productId = id #将id成员变量映射为productId属性
以下是配置文件xbean.xml的内容:
<beans xmlns:p="http://xbean.versus.com/product" > <p:product id="product" productId="1" name="USD/JPY" price="100.00"/> </beans>
以下是测试用的test case:
package com.versus.misc.xbean; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import java.math.BigDecimal; import org.apache.xbean.spring.context.ClassPathXmlApplicationContext; import org.junit.Test; public class XBeanTest { @Test public void test() { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:com/versus/misc/xbean/xbean.xml"); Product product = (Product)context.getBean("product"); assertNotNull(product); assertEquals(1, product.getId()); assertEquals("USD/JPY", product.getName()); assertEquals(new BigDecimal("100.00"), product.getPrice()); } }
4 Constructor injection
除了setter注入之外,XBean也支持constructor注入,以下是个简单的例子:
package com.versus.misc.xbean; import java.math.BigDecimal; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; public class Product { private int id; private String name; private BigDecimal price; private Leverage leverage; public String toString() { return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) .append("id", id) .append("name", name) .append("price", price) .append("leverage", leverage).toString(); } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public BigDecimal getPrice() { return price; } public void setPrice(BigDecimal price) { this.price = price; } public Leverage getLeverage() { return leverage; } public void setLeverage(Leverage leverage) { this.leverage = leverage; } }
package com.versus.misc.xbean; import java.math.BigDecimal; public class Leverage { private int value; private BigDecimal margin; public Leverage(int value, BigDecimal margin) { this.value = value; this.margin = margin; } public int getValue() { return value; } public BigDecimal getMargin() { return margin; } }
META-INF/services/org/apache/xbean/spring/http/xbean.versus.com/product文件的内容如下:
package = com.versus.misc.xbean product = com.versus.misc.xbean.Product leverage = com.versus.misc.xbean.Leverage product.alias.productId = id com.versus.misc.xbean.Leverage(int,java.math.BigDecimal).parameterNames=value margin
以下是配置文件xbean.xml的内容:
<beans xmlns:p="http://xbean.versus.com/product"> <p:product id="product" productId="1" name="##USD/JPY" price="100.00" leverage="#leverage"/> <p:leverage id="leverage" value="50" margin="12345"/> </beans>
以下是测试用的test case:
package com.versus.misc.xbean; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import java.math.BigDecimal; import org.apache.xbean.spring.context.ClassPathXmlApplicationContext; import org.junit.Test; public class XBeanTest { @Test public void test() { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:com/versus/misc/xbean/xbean.xml"); Product product = (Product)context.getBean("product"); assertNotNull(product); assertEquals(1, product.getId()); assertEquals("#USD/JPY", product.getName()); assertEquals(new BigDecimal("100.00"), product.getPrice()); Leverage leverage = (Leverage)context.getBean("leverage"); assertNotNull(leverage); assertEquals(50, leverage.getValue()); assertEquals(new BigDecimal("12345"), leverage.getMargin()); assertEquals(leverage, product.getLeverage()); } }
需要注意的是,以上例子中p:product的leverage属性通过#引用了leverage。如果你期望配置一个以#开头的字符串,那么字符串的需要以##开头(例如以上例子中,product中name成员变量的值是#USD/JPY)。
5 Assembling collections
跟Spring一样,XBean也支持装配集合类型。以上的例子中,假设每种FX交易的商品可以有多个杠杆,那么需要进行以下的修改:
package com.versus.misc.xbean; import java.math.BigDecimal; import java.util.List; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; public class Product { private int id; private String name; private BigDecimal price; private List<Leverage> leverages; public String toString() { return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) .append("id", id) .append("name", name) .append("price", price) .append("leverages", leverages).toString(); } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public BigDecimal getPrice() { return price; } public void setPrice(BigDecimal price) { this.price = price; } public List<Leverage> getLeverages() { return leverages; } public void setLeverages(List<Leverage> leverages) { this.leverages = leverages; } }
META-INF/services/org/apache/xbean/spring/http/xbean.versus.com/product文件的内容如下:
package = com.versus.misc.xbean product = com.versus.misc.xbean.Product leverage = com.versus.misc.xbean.Leverage product.alias.productId = id product.alias.leverages.list = leverages com.versus.misc.xbean.Leverage(int,java.math.BigDecimal).parameterNames=value margin
以下是配置文件xbean.xml的内容:
<beans xmlns:p="http://xbean.versus.com/product"> <p:product id="product" productId="1" name="USD/JPY" price="100.00"> <leverages> <p:leverage id="leverage1" value="50" margin="12345"/> <p:leverage id="leverage2" value="100" margin="24690"/> </leverages> </p:product> </beans>
以下是测试用的test case:
package com.versus.misc.xbean; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import java.math.BigDecimal; import org.apache.xbean.spring.context.ClassPathXmlApplicationContext; import org.junit.Test; public class XBeanTest { @Test public void test() { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:com/versus/misc/xbean/xbean.xml"); Product product = (Product)context.getBean("product"); assertNotNull(product); assertEquals(1, product.getId()); assertEquals("USD/JPY", product.getName()); assertEquals(new BigDecimal("100.00"), product.getPrice()); assertEquals(2, product.getLeverages().size()); Leverage leverage1 = product.getLeverages().get(0); assertNotNull(leverage1); assertEquals(50, leverage1.getValue()); assertEquals(new BigDecimal("12345"), leverage1.getMargin()); Leverage leverage2 = product.getLeverages().get(1); assertNotNull(leverage2); assertEquals(100, leverage2.getValue()); assertEquals(new BigDecimal("24690"), leverage2.getMargin()); } }