我正在使用BeanutilsBean.describe()
方法来获取审计跟踪的数据。它运作得很好 - 这不是问题!
但是,某些属性不需要审核。这些在列表中记录为字符串。因此,例如,如果您有一个属性DomainObject.myValue
,则列表将包含"myValue"
,以便调用DomainObject.getMyValue()
的调用结果不会包含在审计跟踪中。
目前,代码从BeanutilsBean.describe()
获取所有属性,然后遍历它们以丢弃不需要的属性。
我希望能够做的是将BeanUtilsBean
实例配置为要排除的属性名称列表,以便它不会调用这些方法。所以在我的例子中,根本就没有调用DomainObject.getMyValue()。
如果可以通过API或代码查看,我无法解决。
答案 0 :(得分:4)
这是我用来解决这个问题的代码。
这是BeanUtilsBean.describe()
的略微修改的副本,它不会调用被排除的属性getter;这是来自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());
}
}
答案 1 :(得分:1)
不,你正在做的过滤是最简单的方法。该方法的来源不提供任何类型的可配置过滤。使用BeanUtilsBean
时,我只能看到两个选项:
describe()
,然后过滤结果(您现在正在做的事情)。您可以使用带有public static Map<String, String> describeBean(Object bean, String... excludedProperties)
describe()
的实现,但在初始迭代期间执行过滤。这样可以提高性能,因为它不需要额外通过Map
。