4

メソッドを使用BeanutilsBean.describe()して、監査証跡用のデータを取得しています。それは問題なく動作します - それは問題ではありません!

ただし、監査する必要のない特定の属性があります。これらはリストに文字列として記録されます。したがって、たとえばDomainObject.myValue、リストに含まれる属性がある場合"myValue"、呼び出しの結果がDomainObject.getMyValue()監査証跡に含まれないようにします。

現在、コードはすべての属性を取得し、BeanutilsBean.describe()それらを繰り返し処理して不要なものを破棄します。

私ができるようにしたいのはBeanUtilsBean、除外する属性名のリストを使用してインスタンスを構成し、それらのメソッドを呼び出さないようにすることです。したがって、私の例では、 DomainObject.getMyValue() はまったく呼び出されません。

APIまたはコードを調べてそれが可能かどうかはわかりません。

4

2 に答える 2

4

これは、これを解決するために使用したコードです。

BeanUtilsBean.describe()これは、除外された属性ゲッターを呼び出さない、わずかに修正されたコピーです。それは、 ach's answerの「Roll your own」オプションです(最初のオプションは、ライブ コードで数年間使用されていますが、私には合いませんでした!)。

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());
    }

}
于 2013-03-15T11:19:12.290 に答える
1

いいえ、あなたがやっているようにフィルタリングするのが最も簡単な方法です。そのメソッドのソースは、構成可能なフィルタリングの種類を提供しません。を使用しているときに実際に表示できるオプションは 2 つだけBeanUtilsBeanです。

  • 呼び出しdescribe()てから、結果をフィルタリングします (現在行っていること)。これを次のようなシグネチャを持つ静的メソッドにまとめることができますpublic static Map<String, String> describeBean(Object bean, String... excludedProperties)
  • describe()の実装をコピーするが、最初の反復中にフィルタリングを行う独自のユーティリティ メソッド (上記のような署名) をロールします。を介した追加のパスを必要としないため、これによりパフォーマンスが向上しますMap
于 2013-03-12T21:07:16.660 に答える