使用过Javascript和Flex的人,一定对这两种语言的中对象的中动态添加属性感到好奇,特别是Flex,其实如果你仔细看一下Commons-beanUtils的帮助文档,你会发现其实也没有什么,Java也可以实现动态添加属性。
commons-beanutils的常用功能包括类型转换和动态bean的创建。
关于类型转换主要用到BeanUtils 和 ConvertUtils。BeanUtils的使用是大家最熟悉的了。将javax.servlet.HttpServletRequest接受的参数转换到对应到指定的JavaBean,这是Struts等许多MVC框架中的基本服务之一。
在一次HTTP请求中,请求参数值都是字符串或字符串数组,大多数值需要被转换为底层的数据类型。BeanUtils提供了属性的setter方法,以接受字符串的值,并自动把它们转换成合适的属性类型,和getter方法,当调用getter方法时,又进行一次类型转换。除此之外,populate()方法可以把一个map中的键值对转换为bean里面的属性和值。例如
HttpServletRequest request = ...; MyBean bean = ...; HashMap map = new HashMap(); Enumeration names = request.getParameterNames(); while (names.hasMoreElements()) { String name = (String) names.nextElement(); map.put(name, request.getParameterValues(name)); } BeanUtils.populate(bean, map);
当然BeanUtils底层依赖于ConvertUtils。ConvertUtils的使用简单,常用方法如下
static String convert(Object value) //转换指定值为字符串 static Object convert(Object value, Class targetType) //转换指定值为指定的类 static Object convert(String[] values, Class clazz) //将字符串数组转换为指定类型的数组 static Object convert(String value, Class clazz) //转换字符串为一指定类型
下面举例说明(如无特别说明,下面的所有Java代码均以此xml文件为操作对象)
<?xml version="1.0" encoding="UTF-8"?> <origin dataSource="ds"> <columns> <column code="ID" name="" type="java.lang.Integer" length="" /> <column code="FIRSTNAME" name="" type="java.lang.String" length="" /> <column code="LASTNAME" name="" type="java.lang.String" length="" /> <column code="SEX" name="" type="java.lang.String" length="" /> </columns> </origin>
XMLConfiguration config = new XMLConfiguration(String); //关于XML的读取在“commons-configuration的使用”中讲过 String id = config.getString("columns.column.[@code]"); //拿到第一个Column的code String type = config.getString("columns.column.[@type]"); //拿到第一个Column的type Object value = ConvertUtils.convert(id,Class.forName(type)); //转换了
动态bean的创建也很简单,常用API如下
org.apache.commons.beanutils.DynaBean org.apache.commons.beanutils.DynaClass org.apache.commons.beanutils.BasicDynaBean //实现了DynaBean org.apache.commons.beanutils.BasicDynaClass //实现了DynaClass org.apache.commons.beanutils.DynaProperty
第一步,就是要创建动态class
DynaProperty[] props = new DynaProperty[]{ new DynaProperty("address", java.util.Map.class), new DynaProperty("subordinate", mypackage.Employee[].class), new DynaProperty("firstName", String.class), new DynaProperty("lastName", String.class) }; // BasicDynaClass dynaClass = new BasicDynaClass("employee", null, props); //主要是构造props动态属性数组,名字"employee"和bean类型(这里是null)无关紧要
第二步,创建动态bean
DynaBean employee = dynaClass.newInstance(); employee.set("address", new HashMap()); employee.set("subordinate", new mypackage.Employee[0]); employee.set("firstName", "Fred"); employee.set("lastName", "Flintstone");
现在,把xml文件中的所有column属性构造一个动态class(动态class.newInstance()就可以生成一个bean了,所以不讨论动态bean),在如下代码中originDynaClass就是生成的动态class
List<HierarchicalConfiguration> columns = (List<HierarchicalConfiguration>) config.configurationsAt("origin.bean.columns.column"); DynaProperty[] properties = new DynaProperty[columns.size()]; for (int i = 0; i < columns.size(); i++) { HierarchicalConfiguration column = (HierarchicalConfiguration)columns.get(i); try { properties[i] = new DynaProperty(column.getString("[@code]"),Class.forName(column.getString("[@type]"))); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block logger.error("类型转换异常", e); } } BasicDynaClass originDynaClass = new BasicDynaClass ("origin", BasicDynaBean.class, properties);
package cn.com.unutrip.java.opensource.apache.beanutils;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.beanutils.BasicDynaClass;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.DynaClass;
import org.apache.commons.beanutils.DynaProperty;
import org.apache.commons.beanutils.LazyDynaBean;
/**
* BeanUtils中动态bean的学习的应用
*
* @author longgangbai
*
*/
public class DynaBeansExampleV1 {
public static void main(String args[]) throws Exception {
Object movie = createMovieBean();
System.err.println(BeanUtils.getProperty(movie, "title"));
System.err.println(BeanUtils.getProperty(movie, "director.name"));
}
private static Object createMovieBean() throws Exception {
// first create the properties
DynaProperty properties[] = new DynaProperty[] { new DynaProperty("title", String.class), new DynaProperty("dateOfRelease", Date.class),
new DynaProperty("keywords", String[].class), new DynaProperty("genre", Map.class), new DynaProperty("actors", List.class),
new DynaProperty("director", DynaBean.class) };
// next using the properties define the class
DynaClass movieClass = new BasicDynaClass("movie", null, properties);
// now, with the class, create a new instance
DynaBean movieBean = movieClass.newInstance();
// set its properties
movieBean.set("title", "The Italian Job");
movieBean.set("dateOfRelease", new GregorianCalendar(1969, 0, 1).getTime());
movieBean.set("keywords", new String[] { "Italy", "Bank Robbery" });
Map genre = new HashMap();
genre.put("THR", "Thriller");
movieBean.set("genre", genre);
movieBean.set("genre", "ACT", "Action");
DynaBean director = createPersonBean();
director.set("name", "Peter Collinson");
director.set("gender", new Integer(1));
movieBean.set("director", director);
return movieBean;
}
private static DynaBean createPersonBean() {
DynaBean person = new LazyDynaBean();
return person;
}
}