2017-02-26 1 views
1

私は以下のようにFooとItemクラスを持っています。Spring BeanUtilsはListのフィールドを持つプロパティをコピーします

私が春のBeanUtilsを使ってFooクラスをコピーするとき、リストフィールドの参照は変更されません。

import org.springframework.beans.BeanUtils; 

public class SimpleCopyMain { 

    public static void main(String[] args) { 
     Foo foo = new Foo(1L); 
     foo.getItems().add(new Item("item1")); 
     foo.getItems().add(new Item("item2")); 

     Foo fooSnapShot = new Foo(100L); 
     BeanUtils.copyProperties(foo,fooSnapShot); 

     foo.setId(999L); 
     System.out.println("fooSnapShot id field value is not changing as expected : " + fooSnapShot.getId()); 

     foo.getItems().add(new Item("item3")); 

     System.out.println("fooSnapShot items value is changing unexpectedly : " + fooSnapShot.getItems()); 
    } 
} 

SimpleCopyMainクラスの出力は以下の通りです:私は、リストフィールドの新しいインスタンスを作成し、参照を一つずつコピーするとき、私は予想通りしかし、私は動作を取得

fooSnapShot id field value is not changing as expected : 1 
fooSnapShot items value is changing unexpectedly : [Item{bar='item1'}, Item{bar='item2'}, Item{bar='item3'}] 

。ここで

import java.util.ArrayList; 

import org.springframework.beans.BeanUtils; 

public class CopyMain { 

    public static void main(String[] args) { 
     Foo foo = new Foo(1L); 
     foo.getItems().add(new Item("item1")); 
     foo.getItems().add(new Item("item2")); 

     Foo fooSnapShot = new Foo(100L); 
     BeanUtils.copyProperties(foo, fooSnapShot); 

     fooSnapShot.setItems(new ArrayList<Item>(foo.getItems().size())); 
     for(int i = 0; i < foo.getItems().size(); i++){ 
      Item anItem = new Item(""); 
      BeanUtils.copyProperties(foo.getItems().get(i), anItem); 
      fooSnapShot.getItems().add(anItem); 
     } 

     foo.setId(999L); 
     System.out.println("fooSnapShot id field value is not changing as expected : " + fooSnapShot.getId()); 

     foo.getItems().add(new Item("item3")); 

     System.out.println("fooSnapShot items value is is not changing : " + fooSnapShot.getItems()); 
    } 
} 

が出力されます:

fooSnapShot id field value is not changing as expected : 1 
fooSnapShot items value is is not changing : [Item{bar='item1'}, Item{bar='item2'}] 

そして、私のポンポン:

<?xml version="1.0" encoding="UTF-8"?> 
<project xmlns="http://maven.apache.org/POM/4.0.0" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 

    <groupId>com.question</groupId> 
    <artifactId>beanutils</artifactId> 
    <version>1.0-SNAPSHOT</version> 

    <dependencies> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-beans</artifactId> 
      <version>4.3.3.RELEASE</version> 
     </dependency> 
    </dependencies> 
</project> 

なぜ春々BeanUtilsは、リストフィールドのクローンを作成されていませんか?

答えて

1

BeanUtilのcopyProperitiesメソッドの実装によれば、SpringはGettersとSettersでデータをコピーしています。 IntegerのようなプリミティブがあればOKですが、ListフィールドではSetterで参照を渡しています。

あなたはそれが仕事したい場合は、にあなたのセッターを変更する必要があります。これはまた、シャローコピーを行いますが、あなたはリスト参照を持っていません

public void setItems(List<Item> items) { 
     this.items = new ArrayList<>(items); 
} 

1

春のBeanUtils.copyPropertiesを見ると、プロパティの浅いコピーが実行されていることがわかります。プリミティブ値のプロパティのみが複製され、他のすべてのプロパティは参照によってコピーされます。背後では、SpringはPropertyDescriptorを使用してソースプロパティでgetterを呼び出し、ターゲットプロパティでセッターを呼び出しています。

したがって、BeanUtils.copyProperties(foo, fooSnapShot);を呼び出すと、fooとfooSnapShotはアイテムリストと同じ参照を共有するため、fooまたはfooSnapshotインスタンスを通じてリストを変更することができます。ただし、2番目のケースではfooSnapShotに別のList fooSnapShot.setItems(new ArrayList<Item>(foo.getItems().size()));を参照してください。そのため、期待した結果が得られます。

関連する問題