Java/JavaFX企业级应用开发平台(fxEAP)
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

JavaFX属性和绑定02

Object和List

对于简单的包装类型,JavaFX针对性地提供了对应的Property,如StringProperty、IntegerProperty等。但在实际的业务场景中,我们还需要处理一些自定义数据类型、一对一、一对多关系等。在JavaFx中,可以使用ObjectProperty和ListProperty来实现。

ObjectProperty可以用于实现复杂对象的一对一关系,ListProperty可以用于实现复杂对象的一对多关系。

常见的业务对象结构

单体

这是最常见的数据结构(Java Bean/POJO),对应数据库表。

聚合

指一个业务实体中,除了一些简单类型的属性外,还拥有以1:1、1:n方式关联的其它业务实体。即MyBatis中的association和collection。

聚合可以是一主一子、一主多子、多主一子、多主多子、多主等形式。

多对多

指两个业务实体之间存在的交叉引用关系。例如,用户实体和角色实体。一个用户可以拥有多个角色,一个角色也可以分配给多个用户。多对多关系一般使用一张独立的表来保存为种关系。

树形

数据库物理模型中,必须有上级节点、是否末级,这两个字段是用于构造树形结构。可选“当前层级”、“当前层级顺序”字段,用于数据排序。 元数据信息中,需要指定唯一排序字段,用于在没有指定“当前层级”、“当前层级顺序”时进行排序。

自定义Java/JavaFX Bean体系

目标及要求

要展现方便,如枚举、参照等信息,在UI中要显示为业务人员能够看懂的信息,而不是主键、编码等没有业务意义的信息。 要数据库设计结构合理,满足或基本满足数据库第三范式的要求。如不能在集团基本信息表中,保存“国家地区”的编码、名称等信息。 要满足效率尽量优化、性能尽量高、资源占用尽量少等性能要求。要尽量减少访问数据库的次数,减少构造复杂结构的对象。

Java Bean

J1004

JavaFX Bean

J1004

Java Bean和JavaFX Bean

TestVO

其中包含JavaFX的包装类型、新的日期时间类型、自定义枚举类型、参照类型、List类型等。

属性列表

    private String testCode;

    private String testName;

    private Byte testByte;

    private Short testShort;

    private Long testLong;

    private Boolean testBoolean;

    private LocalTime testTime;

    private LocalDateTime testDateTime;

    // 自定义枚举类型
    private ValueObjectStatusEnum valueObjectStatus;

    private Integer testInteger;

    private BigDecimal testDecimal;

    private LocalDate testDate;

    // 自定义参照类型
    private UserReferenceVO pkUser;

    // List
    private List<SubVO> listChild = new ArrayList<>();

getter和setter方法示例

    public Integer getTestInteger() {

        return testInteger;
    }

    public void setTestInteger(Integer testInteger) {

        Integer oldValue = getTestInteger();
        this.testInteger = testInteger;
        firePropertyChange("testInteger", oldValue, testInteger);
    }

firePropertyChange

    /**
     * 属性值变化监听器,用于在javaFX体系下监听属性值的变化,实现双向监听,以保证FXVO和VO中的属性值的一致性
     * 该监听器的作用非常重要。所有需要使用FX体系进行包装的VO,在setter中,都必须使用本监听器通知FX来感知属性值的变化。
     * <p>
     * {@link com.lirong.eap.platform.metadata.pub.vo.PropertyVO}
     */
    @DiffIgnore
    protected final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);

    /**
     * 属性变化事件
     *
     * @param propertyName 属性名称
     * @param oldValue     原值
     * @param newValue     新值
     */
    public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {

        propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
    }

TestFXVO

用于前台界面进行数据处理。由于JavaFX Property不支持序列化机制,所以只能从后台接受Bean,然后封装为JavaFX Bean供前台使用。

属性列表

    private TestVO testVO;

    private StringProperty testCode;

    private StringProperty testName;

    private ObjectProperty<Byte> testByte;

    private ObjectProperty<Short> testShort;

    private ObjectProperty<Long> testLong;

    private ObjectProperty<Boolean> testBoolean;

    private ObjectProperty<LocalTime> testTime;

    private ObjectProperty<LocalDateTime> testDateTime;

    // 自定义枚举类型
    private ObjectProperty<ValueObjectStatusEnum> valueObjectStatus;

    private ObjectProperty<Integer> testInteger;

    private ObjectProperty<BigDecimal> testDecimal;

    private ObjectProperty<LocalDate> testDate;

    // 自定义参照类型
    private ObjectProperty<UserReferenceVO> pkUser;

    // List
    private ListProperty<SubFXVO> listChild;

构造器

FXVO的构造器,应以VO为参数,以便于获取VO传递给后台。

public TestFXVO(TestVO testVO) {

    super();
    setTestVO(testVO);
    initProperty();
}

属性初始化

    protected void initProperty() {

        try {
            // 简单对象
            testCode = JavaBeanStringPropertyBuilder.create().bean(this.testVO).name("testCode").build();
            testName = JavaBeanStringPropertyBuilder.create().bean(this.testVO).name("testName").build();
            testInteger = JavaBeanObjectPropertyBuilder.create().bean(this.testVO).name("testInteger").build();
            testDecimal = JavaBeanObjectPropertyBuilder.create().bean(this.testVO).name("testDecimal").build();
            testDate = JavaBeanObjectPropertyBuilder.create().bean(this.testVO).name("testDate").build();

            testByte = JavaBeanObjectPropertyBuilder.create().bean(this.testVO).name("testByte").build();
            testShort = JavaBeanObjectPropertyBuilder.create().bean(this.testVO).name("testShort").build();
            testLong = JavaBeanObjectPropertyBuilder.create().bean(this.testVO).name("testLong").build();
            testBoolean = JavaBeanObjectPropertyBuilder.create().bean(this.testVO).name("testBoolean").build();
            testTime = JavaBeanObjectPropertyBuilder.create().bean(this.testVO).name("testTime").build();
            testDateTime = JavaBeanObjectPropertyBuilder.create().bean(this.testVO).name("testDateTime").build();
            valueObjectStatus = JavaBeanObjectPropertyBuilder.create().bean(this.testVO).name("valueObjectStatus").build();

            // 参照
            pkUser = JavaBeanObjectPropertyBuilder.create().bean(this.testVO).name("pkUser").build();

            listChild = new SimpleListProperty<>(FXCollections.observableArrayList());

            // vo -> fxvo
            getValueObject().getListChild().forEach(vo -> getListChild().add(new SubFXVO(vo)));

            // fxvo -> vo
            listChild.addListener((ListChangeListener<SubFXVO>) change -> {

                while (change.next()) {
                    if (change.wasAdded()) {
                        for (SubFXVO subFXVO : change.getAddedSubList()) {
                            getValueObject().getListChild().add(subFXVO.getValueObject());
                        }
                    } else if (change.wasRemoved()) {
                        for (SubFXVO subFXVO : change.getRemoved()) {
                            getValueObject().getListChild().remove(subFXVO.getValueObject());
                        }
                    }
                }
            });
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

注意对List类型属性的处理方式。

简单属性绑定测试

测试代码

   /**
     * 验证Bean FXBean的简单属性能够实现双向绑定
     */
    @Test
    public void testSimpleProperty() {

        // bean
        TestVO testVO = new TestVO(100);
        // fx bean
        TestFXVO testFXVO = new TestFXVO(testVO);

        System.out.println("初始值:");
        System.out.println("   Bean:" + testVO);
        System.out.println("FX Bean:" + testFXVO);
        System.out.println();

        // 修改Bean简单属性,看FX Bean是否自动更新
        System.out.println("修改Bean简单属性,看FX Bean是否自动更新:");
        System.out.println(String.format("   Bean修改前的值:TestCode=%s, TestInteger=%s.", testVO.getTestCode(), testVO.getTestInteger()));
        System.out.println(String.format("FX Bean修改前的值:TestCode=%s, TestInteger=%s.", testFXVO.getTestCode(), testFXVO.getTestInteger()));
        testVO.setTestCode("112233");
        testVO.setTestInteger(22);
        System.out.println(String.format("   Bean修改后的值:TestCode=%s, TestInteger=%s.", testVO.getTestCode(), testVO.getTestInteger()));
        System.out.println(String.format("FX Bean修改后的值:TestCode=%s, TestInteger=%s.", testFXVO.getTestCode(), testFXVO.getTestInteger()));
        System.out.println();

        // 修改FX Bean简单属性,看Bean是否自动更新
        System.out.println("修改FX Bean简单属性,看Bean是否自动更新:");
        System.out.println(String.format("   Bean修改前的值:TestDecimal=%s, TestDate=%s.", testVO.getTestDecimal(), testVO.getTestDate()));
        System.out.println(String.format("FX Bean修改前的值:TestDecimal=%s, TestDate=%s.", testFXVO.getTestDecimal(), testFXVO.getTestDecimal()));
        testFXVO.setTestDecimal(new BigDecimal("1234.56"));
        testFXVO.setTestDate(LRDateTimeConverterUtil.parserString2Date("2022-02-02"));
        System.out.println(String.format("   Bean修改后的值:TestDecimal=%s, TestDate=%s.", testVO.getTestDecimal(), testVO.getTestDate()));
        System.out.println(String.format("FX Bean修改后的值:TestDecimal=%s, TestDate=%s.", testFXVO.getTestDecimal(), testFXVO.getTestDecimal()));
    }

测试结果

初始值:
   Bean:TestVO(testCode=TestCode_100, testName=TestName_100, testByte=63, testShort=69, testLong=5495577966595199609, testBoolean=false, testTime=13:26:35.650443400, testDateTime=2021-11-11T11:11:11, valueObjectStatus=NORMAL, testInteger=100, testDecimal=2.5E+4, testDate=1999-09-09, pkUser=UserReferenceVO(), listChild=[SubVO(code=SubCode_1, name=SubName_1), SubVO(code=SubCode_2, name=SubName_2), SubVO(code=SubCode_3, name=SubName_3), SubVO(code=SubCode_4, name=SubName_4), SubVO(code=SubCode_5, name=SubName_5), SubVO(code=SubCode_6, name=SubName_6), SubVO(code=SubCode_7, name=SubName_7), SubVO(code=SubCode_8, name=SubName_8)])
FX Bean:TestFXVO(testVO=TestVO(testCode=TestCode_100, testName=TestName_100, testByte=63, testShort=69, testLong=5495577966595199609, testBoolean=false, testTime=13:26:35.650443400, testDateTime=2021-11-11T11:11:11, valueObjectStatus=NORMAL, testInteger=100, testDecimal=2.5E+4, testDate=1999-09-09, pkUser=UserReferenceVO(), listChild=[SubVO(code=SubCode_1, name=SubName_1), SubVO(code=SubCode_2, name=SubName_2), SubVO(code=SubCode_3, name=SubName_3), SubVO(code=SubCode_4, name=SubName_4), SubVO(code=SubCode_5, name=SubName_5), SubVO(code=SubCode_6, name=SubName_6), SubVO(code=SubCode_7, name=SubName_7), SubVO(code=SubCode_8, name=SubName_8)]), testCode=TestCode_100, testName=TestName_100, testByte=63, testShort=69, testLong=5495577966595199609, testBoolean=false, testTime=13:26:35.650443400, testDateTime=2021-11-11T11:11:11, valueObjectStatus=NORMAL, testInteger=100, testDecimal=2.5E+4, testDate=1999-09-09, pkUser=UserReferenceVO(), listChild=[SubFXVO(basicVO=SubVO(code=SubCode_1, name=SubName_1), code=SubCode_1, name=SubName_1), SubFXVO(basicVO=SubVO(code=SubCode_2, name=SubName_2), code=SubCode_2, name=SubName_2), SubFXVO(basicVO=SubVO(code=SubCode_3, name=SubName_3), code=SubCode_3, name=SubName_3), SubFXVO(basicVO=SubVO(code=SubCode_4, name=SubName_4), code=SubCode_4, name=SubName_4), SubFXVO(basicVO=SubVO(code=SubCode_5, name=SubName_5), code=SubCode_5, name=SubName_5), SubFXVO(basicVO=SubVO(code=SubCode_6, name=SubName_6), code=SubCode_6, name=SubName_6), SubFXVO(basicVO=SubVO(code=SubCode_7, name=SubName_7), code=SubCode_7, name=SubName_7), SubFXVO(basicVO=SubVO(code=SubCode_8, name=SubName_8), code=SubCode_8, name=SubName_8)])

修改Bean简单属性看FX Bean是否自动更新:
   Bean修改前的值TestCode=TestCode_100, TestInteger=100.
FX Bean修改前的值TestCode=TestCode_100, TestInteger=100.
   Bean修改后的值TestCode=112233, TestInteger=22.
FX Bean修改后的值TestCode=112233, TestInteger=22.

修改FX Bean简单属性看Bean是否自动更新:
   Bean修改前的值TestDecimal=2.5E+4, TestDate=1999-09-09.
FX Bean修改前的值TestDecimal=2.5E+4, TestDate=2.5E+4.
   Bean修改后的值TestDecimal=1234.56, TestDate=2022-02-02.
FX Bean修改后的值TestDecimal=1234.56, TestDate=1234.56.

Process finished with exit code 0

可以看出,Bean、FX Bean中的属性,实现了双向绑定。

复杂属性绑定测试

代码

    /**
     * 以List为例,验证Bean FXBean的复杂属性能够实现双向绑定
     */
    @Test
    public void testListProperty() {

        // bean
        TestVO testVO = new TestVO(100);
        // fx bean
        TestFXVO testFXVO = new TestFXVO(testVO);

        // 从bean的list属性中,移除一个元素,看fx bean是否同步更新
        System.out.println("从bean的list属性中,移除一个元素,看fx bean是否同步更新:");
        System.out.println(String.format("   Bean List修改前:大小=%s,信息=%s", testVO.getListChild().size(), testVO.getListChild()));
        System.out.println(String.format("FX Bean List修改前:大小=%s,信息=%s", testFXVO.getListChild().size(), testFXVO.getListChild()));
        testVO.getListChild().remove(2);
        System.out.println(String.format("   Bean List修改后:大小=%s,信息=%s", testVO.getListChild().size(), testVO.getListChild()));
        System.out.println(String.format("FX Bean List修改后:大小=%s,信息=%s", testFXVO.getListChild().size(), testFXVO.getListChild()));
        System.out.println();

        // 从fx bean的list属性中,移除一个元素,看bean是否同步更新
        testVO = new TestVO(200);
        testFXVO = new TestFXVO(testVO);

        System.out.println("从fx bean的list属性中,移除一个元素,看bean是否同步更新:");
        System.out.println(String.format("   Bean List修改前:大小=%s,信息=%s", testVO.getListChild().size(), testVO.getListChild()));
        System.out.println(String.format("FX Bean List修改前:大小=%s,信息=%s", testFXVO.getListChild().size(), testFXVO.getListChild()));
        testFXVO.getListChild().remove(3);
        System.out.println(String.format("   Bean List修改后:大小=%s,信息=%s", testVO.getListChild().size(), testVO.getListChild()));
        System.out.println(String.format("FX Bean List修改后:大小=%s,信息=%s", testFXVO.getListChild().size(), testFXVO.getListChild()));
        System.out.println();

        // 在bean中修改、增加元素
        testVO = new TestVO(300);
        testFXVO = new TestFXVO(testVO);

        System.out.println("在bean中修改、增加元素:");
        System.out.println(String.format("   Bean List修改前:大小=%s,信息=%s", testVO.getListChild().size(), testVO.getListChild()));
        System.out.println(String.format("FX Bean List修改前:大小=%s,信息=%s", testFXVO.getListChild().size(), testFXVO.getListChild()));
        testVO.getListChild().add(0, new SubVO(300));
        testVO.getListChild().get(1).setName("Name_300");
        testVO.getListChild().get(1).setCode("Code_300");
        System.out.println(String.format("   Bean List修改后:大小=%s,信息=%s", testVO.getListChild().size(), testVO.getListChild()));
        System.out.println(String.format("FX Bean List修改后:大小=%s,信息=%s", testFXVO.getListChild().size(), testFXVO.getListChild()));
        System.out.println();

        // 在fx bean中,移除、增加、修改参数
        testVO = new TestVO(400);
        testFXVO = new TestFXVO(testVO);

        System.out.println("在fx bean中,移除、增加、修改参数:");
        System.out.println(String.format("   Bean List修改前:大小=%s,信息=%s", testVO.getListChild().size(), testVO.getListChild()));
        System.out.println(String.format("FX Bean List修改前:大小=%s,信息=%s", testFXVO.getListChild().size(), testFXVO.getListChild()));
        testFXVO.getListChild().add(0, new SubFXVO(new SubVO(400)));
        testFXVO.getListChild().remove(3);
        testFXVO.getListChild().remove(4);
        testFXVO.getListChild().get(1).setName("Name_400");
        testFXVO.getListChild().get(1).setCode("Code_400");
        System.out.println(String.format("   Bean List修改后:大小=%s,信息=%s", testVO.getListChild().size(), testVO.getListChild()));
        System.out.println(String.format("FX Bean List修改后:大小=%s,信息=%s", testFXVO.getListChild().size(), testFXVO.getListChild()));
        System.out.println();
    }

测试结果

1从bean的list属性中移除一个元素看fx bean是否同步更新:
   Bean List修改前大小=5信息=[SubVO(code=SubCode_1, name=SubName_1), SubVO(code=SubCode_2, name=SubName_2), SubVO(code=SubCode_3, name=SubName_3), SubVO(code=SubCode_4, name=SubName_4), SubVO(code=SubCode_5, name=SubName_5)]
FX Bean List修改前大小=5信息=[SubFXVO(basicVO=SubVO(code=SubCode_1, name=SubName_1), code=SubCode_1, name=SubName_1), SubFXVO(basicVO=SubVO(code=SubCode_2, name=SubName_2), code=SubCode_2, name=SubName_2), SubFXVO(basicVO=SubVO(code=SubCode_3, name=SubName_3), code=SubCode_3, name=SubName_3), SubFXVO(basicVO=SubVO(code=SubCode_4, name=SubName_4), code=SubCode_4, name=SubName_4), SubFXVO(basicVO=SubVO(code=SubCode_5, name=SubName_5), code=SubCode_5, name=SubName_5)]
   Bean List修改后大小=4信息=[SubVO(code=SubCode_1, name=SubName_1), SubVO(code=SubCode_2, name=SubName_2), SubVO(code=SubCode_4, name=SubName_4), SubVO(code=SubCode_5, name=SubName_5)]
FX Bean List修改后大小=5信息=[SubFXVO(basicVO=SubVO(code=SubCode_1, name=SubName_1), code=SubCode_1, name=SubName_1), SubFXVO(basicVO=SubVO(code=SubCode_2, name=SubName_2), code=SubCode_2, name=SubName_2), SubFXVO(basicVO=SubVO(code=SubCode_3, name=SubName_3), code=SubCode_3, name=SubName_3), SubFXVO(basicVO=SubVO(code=SubCode_4, name=SubName_4), code=SubCode_4, name=SubName_4), SubFXVO(basicVO=SubVO(code=SubCode_5, name=SubName_5), code=SubCode_5, name=SubName_5)]

2从fx bean的list属性中移除一个元素看bean是否同步更新:
   Bean List修改前大小=9信息=[SubVO(code=SubCode_1, name=SubName_1), SubVO(code=SubCode_2, name=SubName_2), SubVO(code=SubCode_3, name=SubName_3), SubVO(code=SubCode_4, name=SubName_4), SubVO(code=SubCode_5, name=SubName_5), SubVO(code=SubCode_6, name=SubName_6), SubVO(code=SubCode_7, name=SubName_7), SubVO(code=SubCode_8, name=SubName_8), SubVO(code=SubCode_9, name=SubName_9)]
FX Bean List修改前大小=9信息=[SubFXVO(basicVO=SubVO(code=SubCode_1, name=SubName_1), code=SubCode_1, name=SubName_1), SubFXVO(basicVO=SubVO(code=SubCode_2, name=SubName_2), code=SubCode_2, name=SubName_2), SubFXVO(basicVO=SubVO(code=SubCode_3, name=SubName_3), code=SubCode_3, name=SubName_3), SubFXVO(basicVO=SubVO(code=SubCode_4, name=SubName_4), code=SubCode_4, name=SubName_4), SubFXVO(basicVO=SubVO(code=SubCode_5, name=SubName_5), code=SubCode_5, name=SubName_5), SubFXVO(basicVO=SubVO(code=SubCode_6, name=SubName_6), code=SubCode_6, name=SubName_6), SubFXVO(basicVO=SubVO(code=SubCode_7, name=SubName_7), code=SubCode_7, name=SubName_7), SubFXVO(basicVO=SubVO(code=SubCode_8, name=SubName_8), code=SubCode_8, name=SubName_8), SubFXVO(basicVO=SubVO(code=SubCode_9, name=SubName_9), code=SubCode_9, name=SubName_9)]
   Bean List修改后大小=8信息=[SubVO(code=SubCode_1, name=SubName_1), SubVO(code=SubCode_2, name=SubName_2), SubVO(code=SubCode_3, name=SubName_3), SubVO(code=SubCode_5, name=SubName_5), SubVO(code=SubCode_6, name=SubName_6), SubVO(code=SubCode_7, name=SubName_7), SubVO(code=SubCode_8, name=SubName_8), SubVO(code=SubCode_9, name=SubName_9)]
FX Bean List修改后大小=8信息=[SubFXVO(basicVO=SubVO(code=SubCode_1, name=SubName_1), code=SubCode_1, name=SubName_1), SubFXVO(basicVO=SubVO(code=SubCode_2, name=SubName_2), code=SubCode_2, name=SubName_2), SubFXVO(basicVO=SubVO(code=SubCode_3, name=SubName_3), code=SubCode_3, name=SubName_3), SubFXVO(basicVO=SubVO(code=SubCode_5, name=SubName_5), code=SubCode_5, name=SubName_5), SubFXVO(basicVO=SubVO(code=SubCode_6, name=SubName_6), code=SubCode_6, name=SubName_6), SubFXVO(basicVO=SubVO(code=SubCode_7, name=SubName_7), code=SubCode_7, name=SubName_7), SubFXVO(basicVO=SubVO(code=SubCode_8, name=SubName_8), code=SubCode_8, name=SubName_8), SubFXVO(basicVO=SubVO(code=SubCode_9, name=SubName_9), code=SubCode_9, name=SubName_9)]

3在bean中修改增加元素:
   Bean List修改前大小=6信息=[SubVO(code=SubCode_1, name=SubName_1), SubVO(code=SubCode_2, name=SubName_2), SubVO(code=SubCode_3, name=SubName_3), SubVO(code=SubCode_4, name=SubName_4), SubVO(code=SubCode_5, name=SubName_5), SubVO(code=SubCode_6, name=SubName_6)]
FX Bean List修改前大小=6信息=[SubFXVO(basicVO=SubVO(code=SubCode_1, name=SubName_1), code=SubCode_1, name=SubName_1), SubFXVO(basicVO=SubVO(code=SubCode_2, name=SubName_2), code=SubCode_2, name=SubName_2), SubFXVO(basicVO=SubVO(code=SubCode_3, name=SubName_3), code=SubCode_3, name=SubName_3), SubFXVO(basicVO=SubVO(code=SubCode_4, name=SubName_4), code=SubCode_4, name=SubName_4), SubFXVO(basicVO=SubVO(code=SubCode_5, name=SubName_5), code=SubCode_5, name=SubName_5), SubFXVO(basicVO=SubVO(code=SubCode_6, name=SubName_6), code=SubCode_6, name=SubName_6)]
   Bean List修改后大小=7信息=[SubVO(code=SubCode_300, name=SubName_300), SubVO(code=Code_300, name=Name_300), SubVO(code=SubCode_2, name=SubName_2), SubVO(code=SubCode_3, name=SubName_3), SubVO(code=SubCode_4, name=SubName_4), SubVO(code=SubCode_5, name=SubName_5), SubVO(code=SubCode_6, name=SubName_6)]
FX Bean List修改后大小=6信息=[SubFXVO(basicVO=SubVO(code=Code_300, name=Name_300), code=Code_300, name=Name_300), SubFXVO(basicVO=SubVO(code=SubCode_2, name=SubName_2), code=SubCode_2, name=SubName_2), SubFXVO(basicVO=SubVO(code=SubCode_3, name=SubName_3), code=SubCode_3, name=SubName_3), SubFXVO(basicVO=SubVO(code=SubCode_4, name=SubName_4), code=SubCode_4, name=SubName_4), SubFXVO(basicVO=SubVO(code=SubCode_5, name=SubName_5), code=SubCode_5, name=SubName_5), SubFXVO(basicVO=SubVO(code=SubCode_6, name=SubName_6), code=SubCode_6, name=SubName_6)]

4在fx bean中移除增加修改参数:
   Bean List修改前大小=9信息=[SubVO(code=SubCode_1, name=SubName_1), SubVO(code=SubCode_2, name=SubName_2), SubVO(code=SubCode_3, name=SubName_3), SubVO(code=SubCode_4, name=SubName_4), SubVO(code=SubCode_5, name=SubName_5), SubVO(code=SubCode_6, name=SubName_6), SubVO(code=SubCode_7, name=SubName_7), SubVO(code=SubCode_8, name=SubName_8), SubVO(code=SubCode_9, name=SubName_9)]
FX Bean List修改前大小=9信息=[SubFXVO(basicVO=SubVO(code=SubCode_1, name=SubName_1), code=SubCode_1, name=SubName_1), SubFXVO(basicVO=SubVO(code=SubCode_2, name=SubName_2), code=SubCode_2, name=SubName_2), SubFXVO(basicVO=SubVO(code=SubCode_3, name=SubName_3), code=SubCode_3, name=SubName_3), SubFXVO(basicVO=SubVO(code=SubCode_4, name=SubName_4), code=SubCode_4, name=SubName_4), SubFXVO(basicVO=SubVO(code=SubCode_5, name=SubName_5), code=SubCode_5, name=SubName_5), SubFXVO(basicVO=SubVO(code=SubCode_6, name=SubName_6), code=SubCode_6, name=SubName_6), SubFXVO(basicVO=SubVO(code=SubCode_7, name=SubName_7), code=SubCode_7, name=SubName_7), SubFXVO(basicVO=SubVO(code=SubCode_8, name=SubName_8), code=SubCode_8, name=SubName_8), SubFXVO(basicVO=SubVO(code=SubCode_9, name=SubName_9), code=SubCode_9, name=SubName_9)]
   Bean List修改后大小=8信息=[SubVO(code=Code_400, name=Name_400), SubVO(code=SubCode_2, name=SubName_2), SubVO(code=SubCode_4, name=SubName_4), SubVO(code=SubCode_6, name=SubName_6), SubVO(code=SubCode_7, name=SubName_7), SubVO(code=SubCode_8, name=SubName_8), SubVO(code=SubCode_9, name=SubName_9), SubVO(code=SubCode_400, name=SubName_400)]
FX Bean List修改后大小=8信息=[SubFXVO(basicVO=SubVO(code=SubCode_400, name=SubName_400), code=SubCode_400, name=SubName_400), SubFXVO(basicVO=SubVO(code=Code_400, name=Name_400), code=Code_400, name=Name_400), SubFXVO(basicVO=SubVO(code=SubCode_2, name=SubName_2), code=SubCode_2, name=SubName_2), SubFXVO(basicVO=SubVO(code=SubCode_4, name=SubName_4), code=SubCode_4, name=SubName_4), SubFXVO(basicVO=SubVO(code=SubCode_6, name=SubName_6), code=SubCode_6, name=SubName_6), SubFXVO(basicVO=SubVO(code=SubCode_7, name=SubName_7), code=SubCode_7, name=SubName_7), SubFXVO(basicVO=SubVO(code=SubCode_8, name=SubName_8), code=SubCode_8, name=SubName_8), SubFXVO(basicVO=SubVO(code=SubCode_9, name=SubName_9), code=SubCode_9, name=SubName_9)]


Process finished with exit code 0
  1. 从bean的list属性中,移除一个元素,看fx bean是否同步更新

    可以发现有问题。bean中的list变化时,fx bean无法感知。

  2. 从fx bean的list属性中,移除一个元素,看bean是否同步更新

    fx bean中的list变化时,会处理bean中的数据。

  3. 在bean中修改、增加元素

    同第一种情况,bean中的元素变化时,fx bean无法感知。

  4. 在fx bean中,移除、增加、修改参数

    fx bean中的list变化时,会处理bean中的数据。

总结

  • 对于简单类型的属性(String、Integer、BigDecimal等)来说,能够实现bean、fx bean之间的双向绑定
  • 对于复杂类型的属性(List、Set等)来说,fx bean会把元素变化传递给bean,而反之则不行