這是我用來解決這個問題的代碼。
這是BeanUtilsBean.describe()
的略微修改副本,它不會調用排除的屬性獲取器;它是ach's answer中的「滾動你自己」選項(第一個選項已經在現場代碼中使用了幾年,但它從來沒有和我一起坐過!)。
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.DynaProperty;
import org.apache.commons.beanutils.MethodUtils;
public class BeanUtilsBeanExtensions {
private static final BeanUtilsBean BEAN_UTILS_BEAN = BeanUtilsBean
.getInstance();
public BeanUtilsBeanExtensions() {
}
/**
* Extends BeanUtilsBean.describe() so that it can be given a list of
* attributes to exclude. This avoids calling methods which might derive
* data which don't happen to be populated when the describe() call is made
* (and therefore could throw exceptions) as well as being more efficient
* than describing everything then discarding attributes which aren't
* required.
*
* @param bean
* See BeanUtilsBean.describe()
* @param excludedAttributeNames
* the attribute names which should not be described.
* @return See BeanUtilsBean.describe()
*/
public Map<String, String> describe(Object bean,
Set<String> excludedAttributeNames)
throws IllegalAccessException,
InvocationTargetException, NoSuchMethodException {
// This method is mostly just a copy/paste from BeanUtilsBean.describe()
// The only changes are:
// - Removal of reference to the (private) logger
// - Addition of Reference to a BeanUtilsBean instance
// - Addition of calls to excludedAttributeNames.contains(name)
// - Use of generics on the Collections
// - Calling of a copy of PropertyUtilsBean.getReadMethod()
if (bean == null) {
return (new java.util.HashMap<String, String>());
}
Map<String, String> description = new HashMap<String, String>();
if (bean instanceof DynaBean) {
DynaProperty[] descriptors = ((DynaBean) bean).getDynaClass()
.getDynaProperties();
for (int i = 0; i < descriptors.length; i++) {
String name = descriptors[i].getName();
if (!excludedAttributeNames.contains(name)) {
description.put(name,
BEAN_UTILS_BEAN.getProperty(bean, name));
}
}
}
else {
PropertyDescriptor[] descriptors = BEAN_UTILS_BEAN
.getPropertyUtils().getPropertyDescriptors(bean);
Class<? extends Object> clazz = bean.getClass();
for (int i = 0; i < descriptors.length; i++) {
String name = descriptors[i].getName();
if (!excludedAttributeNames.contains(name)
&& getReadMethod(clazz, descriptors[i]) != null) {
description.put(name,
BEAN_UTILS_BEAN.getProperty(bean, name));
}
}
}
return description;
}
/*
* Copy of PropertyUtilsBean.getReadMethod() since that is package-private.
*/
private Method getReadMethod(Class<? extends Object> clazz,
PropertyDescriptor descriptor) {
return MethodUtils.getAccessibleMethod(clazz,
descriptor.getReadMethod());
}
}