Java/library/commons-beanutils

更新日: 2020-05-10 (日) 00:08:46 (399d)

Java

Commons BeanUtils

  • JavaBean規約に沿ったオブジェクト操作を容易にしてくれる様々な機能を提供してくれるライブラリ
  • Apache Commonsプロジェクトの1つ

インストール

maven

mavenでインストールする場合は、以下のような指定となる。

<dependency>
    <groupId>commons-beanutils</groupId>
    <artifactId>commons-beanutils</artifactId>
    <version>1.9.3</version>
</dependency>

参考MvnRepository - on https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils

個別にjarを設置する

jarファイルを個別にインストールする場合、1.9.3では以下のようになる。

  • commons-beanutils-1.9.3.jar
  • commons-logging-1.2.jar
  • commons-collections-3.2.2.jar

commons-loggingやcommons-collectionsが必要となる。commons-collectionsは、4からgroupとartifactが変更されているので注意する。1.9.3では、commons-collectionsを利用する。

DynaBean、DynaClass、DynaProperty

これらのクラスは、BeanのようなJavaオブジェクトを表現するためのベースクラス達である。
それぞれ以下の役割を持つ。

  • DynaBean
    • リストやマップのようなプロパティを操作可能とするクラスである。
      DynaBeanにプロパティを設定すると、DynaClassにプロパティ情報が伝えられる。
      POJOのようなオブジェクトは、WrapDynaBeanというクラスでラップされ扱われる。
  • DynaClass
    • DynaBeanのプロパティ情報を保持するクラスである。
  • DynaProperty
    • DynaBeanの個々のプロパティ表現である。

LazyDynaList

このクラスは、ArrayList<Object>を継承したクラスであり、主に以下の機能を有する。

  1. サイズを自動拡張してくれ、指定のpositionに要素を挿入することができる。
  2. 配列やCollectionをLazyDynaListに挿入する。指定の位置にCollectionの要素を挿入することができる。

LazyDynaListの要素の型

LazyDynaListに格納されるオブジェクトは、DynaBeanクラスとして管理される。
追加されるオブジェクトの型によって異なる。

対応する型
MapLazyDynaMap
POJOWrapDynaBean
DynaBeanDynaBean

要素タイプの指定がない場合は、LazyDynaBeantとLazyDynaClassが使われる。

Map型を扱う

/*
 * 1. Mapの配列を扱う
 */
System.out.println("[1]");

// Mapの配列を作成
HashMap[] myMapArray = new HashMap[1];
myMapArray[0] = new HashMap<String, Object>();
myMapArray[0].put("name", "mapValue");
// Mapの配列を追加して初期化
LazyDynaList lazyList = new LazyDynaList(myMapArray);
// リサイズ時に失敗しないように要素のタイプを指定しておく。
// この指定がないと、すでに要素がある状態でelementTypeを設定しようとしてエラーとなる。(この時点では、まだelementTypeがない)
// DynaClassはLazyDynaMapであり、このDynaClassはMap型のオブジェクトを生成して返す。
lazyList.setElementType(HashMap.class);
//lazyList.setElementType(TreeMap.class);

// サイズ拡張で、新しい要素オブジェクトを得る、LazyDynaMap型である。
DynaBean newElement = (DynaBean) lazyList.get(lazyList.size());
newElement.set("name", "arrayValue");
DynaBean element = (DynaBean) lazyList.get(lazyList.size() - 1);
System.out.println(element.get("name"));

Map<String, String>[] maps = (Map<String, String>[]) lazyList.toArray();
Arrays.stream(maps).forEach(m -> {
    m.forEach((k, v) -> System.out.println(k + ":" + v));
});


/*
 * 2. Listを扱う
 */
System.out.println("[2]");

List<Map<String, String>> myList = new ArrayList<>();
lazyList = new LazyDynaList(myList);
// サイズ拡張, elementTypeはLazyDynaBeanである
newElement = (DynaBean) lazyList.get(lazyList.size());
newElement.set("name", "listValue");
element = (DynaBean) lazyList.get(lazyList.size() - 1);
// この時点でelementTypeはLazyDynaBeanとなっている。
System.out.println(element.get("name"));

// elementTypeのオブジェクトを追加する。
LazyDynaBean newBean = new LazyDynaBean();
newBean.set("name", "elementValue");
lazyList.add(newBean);
element = (DynaBean) lazyList.get(lazyList.size() - 1);
System.out.println(element.get("name"));

// LazyDynaBeanでない型の追加はエラーとなる。
HashMap<String, Object> map = new HashMap<String, Object>();
lazyList.add(map);
// Exception in thread "main" java.lang.IllegalArgumentException: Element Type class java.util.HashMap doesn't match other elements class org.apache.commons.beanutils.LazyDynaBean

/*
[1]
arrayValue
name:mapValue
name:arrayValue
[2]
listValue
elementValue
Exception in thread "main" java.lang.IllegalArgumentException: Element Type class java.util.HashMap doesn't match other elements class org.apache.commons.beanutils.LazyDynaBean
	at org.apache.commons.beanutils.LazyDynaList.transform(LazyDynaList.java:689)
	at org.apache.commons.beanutils.LazyDynaList.add(LazyDynaList.java:288)
	at cb.LazyDynaListSample.main(LazyDynaListSample.java:122)
*/

この機能は、例えばHTMLフォームから要素の配列を受け取り、Listにセットするような状況で役に立つ。
例えば以下のような使い方ができるだろう。

HTMLフォーム配列を受け取る例

package cb;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.HashMap;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.LazyDynaList;
import org.apache.commons.beanutils.WrapDynaBean;

public class LazyDynaListTest {

    public static class MyBean implements Serializable {
        private String name;
        private int age;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        @Override
        public String toString() {
            return String.format("name:%s, age:%d", name, age);
        }
    }

    public static class MyForm {
        LazyDynaList list = new LazyDynaList(MyBean.class);

        public LazyDynaList getList() {
            return list;
        }

        public void setList(LazyDynaList list) {
            this.list = list;
        }

        public void bind(HashMap<String, Object> parameters)
                throws IllegalAccessException, InvocationTargetException {
            BeanUtils.populate(this, parameters);
        }
    }

    public static void main(String[] args) throws Exception {
        MyForm form = new MyForm();

        HashMap<String, Object> parameters = new HashMap<String, Object>() {
            {
                put("list[0].name", "hoge");
                put("list[0].age", 100);

                put("list[1].name", "foo");
                put("list[1].age", 200);
            }
        };

        form.bind(parameters);

        // POJOは、WrapDynaBeanとして格納されている。
        Arrays.stream(form.getList().toArray(new WrapDynaBean[0]))
                .forEach(v -> {
                    // instanceメンバにMyBeanのインスタンスがある。
                    MyBean bean = (MyBean)v.getInstance();
                    System.out.println(String.format("name: %s, age: %d",
                            bean.getName(), bean.getAge()));
                    // DynaBeanからアクセスする場合は、プロパティ名を指定すれば良い。
                    System.out.println(String.format("name: %s, age: %d",
                            v.get("name"), v.get("age")));
                });
    }
}

参考 Maven Repository

参考リンク


トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
目次
TOP | 閉じる | ダブルクリックで閉じる