很多人会说:BeanUtils的
public static void populate(Object bean, Map properties)
throws IllegalAccessException, InvocationTargetException
{
BeanUtilsBean.getInstance().populate(bean, properties);
}
这个方法,是的没错。
下面我们来分析一下他的源码:
package org.apache.commons.beanutils;
import java.beans.IndexedPropertyDescriptor;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.beanutils.expression.Resolver;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class BeanUtilsBean
{
private static final ContextClassLoaderLocal BEANS_BY_CLASSLOADER = new ContextClassLoaderLocal()
{
protected Object initialValue() {
return new BeanUtilsBean();
}
};
private Log log = LogFactory.getLog(BeanUtils.class);
private ConvertUtilsBean convertUtilsBean;
private PropertyUtilsBean propertyUtilsBean;
private static final Method INIT_CAUSE_METHOD = getInitCauseMethod();
public static BeanUtilsBean getInstance()
{
return (BeanUtilsBean)BEANS_BY_CLASSLOADER.get();
}
public static void setInstance(BeanUtilsBean newInstance)
{
BEANS_BY_CLASSLOADER.set(newInstance);
}
public BeanUtilsBean()
{
this(new ConvertUtilsBean(), new PropertyUtilsBean());
}
public BeanUtilsBean(ConvertUtilsBean convertUtilsBean)
{
this(convertUtilsBean, new PropertyUtilsBean());
}
public BeanUtilsBean(ConvertUtilsBean convertUtilsBean, PropertyUtilsBean propertyUtilsBean)
{
this.convertUtilsBean = convertUtilsBean;
this.propertyUtilsBean = propertyUtilsBean;
}
public Object cloneBean(Object bean)
throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException
{
if (log.isDebugEnabled()) {
log.debug("Cloning bean: " + bean.getClass().getName());
}
Object newBean = null;
if ((bean instanceof DynaBean))
newBean = ((DynaBean)bean).getDynaClass().newInstance();
else {
newBean = bean.getClass().newInstance();
}
getPropertyUtils().copyProperties(newBean, bean);
return newBean;
}
public void copyProperties(Object dest, Object orig)
throws IllegalAccessException, InvocationTargetException
{
if (dest == null) {
throw new IllegalArgumentException("No destination bean specified");
}
if (orig == null) {
throw new IllegalArgumentException("No origin bean specified");
}
if (log.isDebugEnabled()) {
log.debug("BeanUtils.copyProperties(" + dest + ", " + orig + ")");
}
if ((orig instanceof DynaBean)) {
DynaProperty[] origDescriptors = ((DynaBean)orig).getDynaClass().getDynaProperties();
for (int i = 0; i < origDescriptors.length; i++) {
String name = origDescriptors[i].getName();
if ((getPropertyUtils().isReadable(orig, name)) && (getPropertyUtils().isWriteable(dest, name)))
{
Object value = ((DynaBean)orig).get(name);
copyProperty(dest, name, value);
}
}
} else if ((orig instanceof Map)) {
Iterator entries = ((Map)orig).entrySet().iterator();
while (entries.hasNext()) {
Map.Entry entry = (Map.Entry)entries.next();
String name = (String)entry.getKey();
if (getPropertyUtils().isWriteable(dest, name))
copyProperty(dest, name, entry.getValue());
}
}
else {
PropertyDescriptor[] origDescriptors = getPropertyUtils().getPropertyDescriptors(orig);
for (int i = 0; i < origDescriptors.length; i++) {
String name = origDescriptors[i].getName();
if (!"class".equals(name))
{
if ((getPropertyUtils().isReadable(orig, name)) && (getPropertyUtils().isWriteable(dest, name)))
try
{
Object value = getPropertyUtils().getSimpleProperty(orig, name);
copyProperty(dest, name, value);
}
catch (NoSuchMethodException e)
{
}
}
}
}
}
public void copyProperty(Object bean, String name, Object value)
throws IllegalAccessException, InvocationTargetException
{
if (log.isTraceEnabled()) {
StringBuffer sb = new StringBuffer(" copyProperty(");
sb.append(bean);
sb.append(", ");
sb.append(name);
sb.append(", ");
if (value == null) {
sb.append("");
} else if ((value instanceof String)) {
sb.append((String)value);
} else if ((value instanceof String[])) {
String[] values = (String[])value;
sb.append('[');
for (int i = 0; i < values.length; i++) {
if (i > 0) {
sb.append(',');
}
sb.append(values[i]);
}
sb.append(']');
} else {
sb.append(value.toString());
}
sb.append(')');
log.trace(sb.toString());
}
Object target = bean;
Resolver resolver = getPropertyUtils().getResolver();
while (resolver.hasNested(name)) {
try {
target = getPropertyUtils().getProperty(target, resolver.next(name));
name = resolver.remove(name);
} catch (NoSuchMethodException e) {
return;
}
}
if (log.isTraceEnabled()) {
log.trace(" Target bean = " + target);
log.trace(" Target name = " + name);
}
String propName = resolver.getProperty(name);
Class type = null;
int index = resolver.getIndex(name);
String key = resolver.getKey(name);
if ((target instanceof DynaBean)) {
DynaClass dynaClass = ((DynaBean)target).getDynaClass();
DynaProperty dynaProperty = dynaClass.getDynaProperty(propName);
if (dynaProperty == null) {
return;
}
type = dynaProperty.getType();
} else {
PropertyDescriptor descriptor = null;
try {
descriptor = getPropertyUtils().getPropertyDescriptor(target, name);
if (descriptor == null)
return;
}
catch (NoSuchMethodException e) {
return;
}
type = descriptor.getPropertyType();
if (type == null)
{
if (log.isTraceEnabled()) {
log.trace(" target type for property '" + propName + "' is null, so skipping ths setter");
}
return;
}
}
if (log.isTraceEnabled()) {
log.trace(" target propName=" + propName + ", type=" + type + ", index=" + index + ", key=" + key);
}
if (index >= 0) {
value = convert(value, type.getComponentType());
try {
getPropertyUtils().setIndexedProperty(target, propName, index, value);
}
catch (NoSuchMethodException e) {
throw new InvocationTargetException(e, "Cannot set " + propName);
}
}
else if (key != null)
{
try
{
getPropertyUtils().setMappedProperty(target, propName, key, value);
}
catch (NoSuchMethodException e) {
throw new InvocationTargetException(e, "Cannot set " + propName);
}
}
else {
value = convert(value, type);
try {
getPropertyUtils().setSimpleProperty(target, propName, value);
} catch (NoSuchMethodException e) {
throw new InvocationTargetException(e, "Cannot set " + propName);
}
}
}
public Map describe(Object bean)
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException
{
if (bean == null)
{
return new HashMap();
}
if (log.isDebugEnabled()) {
log.debug("Describing bean: " + bean.getClass().getName());
}
Map description = new HashMap();
if ((bean instanceof DynaBean)) {
DynaProperty[] descriptors = ((DynaBean)bean).getDynaClass().getDynaProperties();
for (int i = 0; i < descriptors.length; i++) {
String name = descriptors[i].getName();
description.put(name, getProperty(bean, name));
}
} else {
PropertyDescriptor[] descriptors = getPropertyUtils().getPropertyDescriptors(bean);
Class clazz = bean.getClass();
for (int i = 0; i < descriptors.length; i++) {
String name = descriptors[i].getName();
if (getPropertyUtils().getReadMethod(clazz, descriptors[i]) != null) {
description.put(name, getProperty(bean, name));
}
}
}
return description;
}
public String[] getArrayProperty(Object bean, String name)
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException
{
Object value = getPropertyUtils().getProperty(bean, name);
if (value == null)
return null;
if ((value instanceof Collection)) {
ArrayList values = new ArrayList();
Iterator items = ((Collection)value).iterator();
while (items.hasNext()) {
Object item = items.next();
if (item == null) {
values.add((String)null);
}
else {
values.add(getConvertUtils().convert(item));
}
}
return (String[])values.toArray(new String[values.size()]);
}if (value.getClass().isArray()) {
int n = Array.getLength(value);
String[] results = new String[n];
for (int i = 0; i < n; i++) {
Object item = Array.get(value, i);
if (item == null) {
results[i] = null;
}
else {
results[i] = getConvertUtils().convert(item);
}
}
return results;
}
String[] results = new String[1];
results[0] = getConvertUtils().convert(value);
return results;
}
public String getIndexedProperty(Object bean, String name)
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException
{
Object value = getPropertyUtils().getIndexedProperty(bean, name);
return getConvertUtils().convert(value);
}
public String getIndexedProperty(Object bean, String name, int index)
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException
{
Object value = getPropertyUtils().getIndexedProperty(bean, name, index);
return getConvertUtils().convert(value);
}
public String getMappedProperty(Object bean, String name)
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException
{
Object value = getPropertyUtils().getMappedProperty(bean, name);
return getConvertUtils().convert(value);
}
public String getMappedProperty(Object bean, String name, String key)
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException
{
Object value = getPropertyUtils().getMappedProperty(bean, name, key);
return getConvertUtils().convert(value);
}
public String getNestedProperty(Object bean, String name)
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException
{
Object value = getPropertyUtils().getNestedProperty(bean, name);
return getConvertUtils().convert(value);
}
public String getProperty(Object bean, String name)
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException
{
return getNestedProperty(bean, name);
}
public String getSimpleProperty(Object bean, String name)
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException
{
Object value = getPropertyUtils().getSimpleProperty(bean, name);
return getConvertUtils().convert(value);
}
public void populate(Object bean, Map properties)
throws IllegalAccessException, InvocationTargetException
{
if ((bean == null) || (properties == null)) {
return;
}
if (log.isDebugEnabled()) {
log.debug("BeanUtils.populate(" + bean + ", " + properties + ")");
}
Iterator entries = properties.entrySet().iterator();
while (entries.hasNext())
{
Map.Entry entry = (Map.Entry)entries.next();
String name = (String)entry.getKey();
if (name != null)
{
setProperty(bean, name, entry.getValue());
}
}
}
public void setProperty(Object bean, String name, Object value)
throws IllegalAccessException, InvocationTargetException
{
if (log.isTraceEnabled()) {
StringBuffer sb = new StringBuffer(" setProperty(");
sb.append(bean);
sb.append(", ");
sb.append(name);
sb.append(", ");
if (value == null) {
sb.append("");
} else if ((value instanceof String)) {
sb.append((String)value);
} else if ((value instanceof String[])) {
String[] values = (String[])value;
sb.append('[');
for (int i = 0; i < values.length; i++) {
if (i > 0) {
sb.append(',');
}
sb.append(values[i]);
}
sb.append(']');
} else {
sb.append(value.toString());
}
sb.append(')');
log.trace(sb.toString());
}
Object target = bean;
Resolver resolver = getPropertyUtils().getResolver();
while (resolver.hasNested(name)) {
try {
target = getPropertyUtils().getProperty(target, resolver.next(name));
name = resolver.remove(name);
} catch (NoSuchMethodException e) {
return;
}
}
if (log.isTraceEnabled()) {
log.trace(" Target bean = " + target);
log.trace(" Target name = " + name);
}
String propName = resolver.getProperty(name);
Class type = null;
int index = resolver.getIndex(name);
String key = resolver.getKey(name);
if ((target instanceof DynaBean)) {
DynaClass dynaClass = ((DynaBean)target).getDynaClass();
DynaProperty dynaProperty = dynaClass.getDynaProperty(propName);
if (dynaProperty == null) {
return;
}
type = dynaProperty.getType();
} else if ((target instanceof Map)) {
type = Object.class;
} else if ((target.getClass().isArray()) && (index >= 0)) {
type = Array.get(target, index).getClass();
} else {
PropertyDescriptor descriptor = null;
try {
descriptor = getPropertyUtils().getPropertyDescriptor(target, name);
if (descriptor == null)
return;
}
catch (NoSuchMethodException e) {
return;
}
if ((descriptor instanceof MappedPropertyDescriptor)) {
if (((MappedPropertyDescriptor)descriptor).getMappedWriteMethod() == null) {
if (log.isDebugEnabled()) {
log.debug("Skipping read-only property");
}
return;
}
type = ((MappedPropertyDescriptor)descriptor).getMappedPropertyType();
}
else if ((index >= 0) && ((descriptor instanceof IndexedPropertyDescriptor))) {
if (((IndexedPropertyDescriptor)descriptor).getIndexedWriteMethod() == null) {
if (log.isDebugEnabled()) {
log.debug("Skipping read-only property");
}
return;
}
type = ((IndexedPropertyDescriptor)descriptor).getIndexedPropertyType();
}
else if (key != null) {
if (descriptor.getReadMethod() == null) {
if (log.isDebugEnabled()) {
log.debug("Skipping read-only property");
}
return;
}
type = value == null ? Object.class : value.getClass();
} else {
if (descriptor.getWriteMethod() == null) {
if (log.isDebugEnabled()) {
log.debug("Skipping read-only property");
}
return;
}
type = descriptor.getPropertyType();
}
}
Object newValue = null;
if ((type.isArray()) && (index < 0)) {
if (value == null) {
String[] values = new String[1];
values[0] = null;
newValue = getConvertUtils().convert(values, type);
} else if ((value instanceof String)) {
newValue = getConvertUtils().convert(value, type);
} else if ((value instanceof String[])) {
newValue = getConvertUtils().convert((String[])value, type);
} else {
newValue = convert(value, type);
}
} else if (type.isArray()) {
if (((value instanceof String)) || (value == null)) {
newValue = getConvertUtils().convert((String)value, type.getComponentType());
}
else if ((value instanceof String[])) {
newValue = getConvertUtils().convert(((String[])(String[])value)[0], type.getComponentType());
}
else {
newValue = convert(value, type.getComponentType());
}
}
else if ((value instanceof String))
newValue = getConvertUtils().convert((String)value, type);
else if ((value instanceof String[])) {
newValue = getConvertUtils().convert(((String[])(String[])value)[0], type);
}
else {
newValue = convert(value, type);
}
try
{
getPropertyUtils().setProperty(target, name, newValue);
} catch (NoSuchMethodException e) {
throw new InvocationTargetException(e, "Cannot set " + propName);
}
}
public ConvertUtilsBean getConvertUtils()
{
return convertUtilsBean;
}
public PropertyUtilsBean getPropertyUtils()
{
return propertyUtilsBean;
}
public boolean initCause(Throwable throwable, Throwable cause)
{
if ((INIT_CAUSE_METHOD != null) && (cause != null)) {
try {
INIT_CAUSE_METHOD.invoke(throwable, new Object[] { cause });
return true;
} catch (Throwable e) {
return false;
}
}
return false;
}
protected Object convert(Object value, Class type)
{
Converter converter = getConvertUtils().lookup(type);
if (converter != null) {
log.trace(" USING CONVERTER " + converter);
return converter.convert(type, value);
}
return value;
}
private static Method getInitCauseMethod()
{
try
{
Class[] paramsClasses = { Throwable.class };
return Throwable.class.getMethod("initCause", paramsClasses);
} catch (NoSuchMethodException e) {
Log log = LogFactory.getLog(BeanUtils.class);
if (log.isWarnEnabled()) {
log.warn("Throwable does not have initCause() method in JDK 1.3");
}
return null;
} catch (Throwable e) {
Log log = LogFactory.getLog(BeanUtils.class);
if (log.isWarnEnabled())
log.warn("Error getting the Throwable initCause() method", e);
}
return null;
}
}