简体   繁体   English

将自定义事件侦听器添加到Java bean中以进行设置

[英]Adding a custom event listener into java bean for setters

I have a bean which has lot of property and half of them n to n relationship. 我有一个具有很多特性的bean,其中一半具有n对n的关系。 I have also added additional transient ' isEdited ' boolean to make sure user has done some changes so I can reduce db fetch for all entities. 我还添加了其他瞬态' isEdited '布尔值,以确保用户进行了一些更改,以便减少所有实体的数据库获取。 My current problem sometimes I need to serialize my bean and want to compare properties with real instance. 我当前的问题有时需要序列化bean,并想将属性与真实实例进行比较。 First solution I have tried is from apache commons-lang => EqualsBuilder.reflectEqual(); 我尝试过的第一个解决方案是来自apache commons-lang => EqualsBuilder.reflectEqual(); method which doesnt works well for me because some of inherited items doesn`t implements equals method in right way and I can not edit them. 该方法对我而言效果不佳,因为某些继承项无法以正确的方式实现equals方法,因此我无法对其进行编辑。 I know I can add ajax listeners to update edited property or I can update each setter method or a new equals implementation. 我知道我可以添加ajax侦听器来更新已编辑的属性,也可以更新每个setter方法或新的equals实现。 But I am looking for little bit more practical and generic way so I can use this implementation also in the future as well. 但是我正在寻找一些更实用和通用的方法,以便将来也可以使用此实现。

So what I want:( Lets say I have a simple bean): 所以我想要什么:(可以说我有一个简单的bean):

public class Foo {

    private String prop1;

    private String prop2;

    /**
     * @return the prop1
     */
    public String getProp1() {
        return prop1;
    }

    /**
     * @param prop1 the prop1 to set
     */
    public void setProp1(String prop1) {
        this.prop1 = prop1;
    }

    /**
     * @return the prop2
     */
    public String getProp2() {
        return prop2;
    }

    /**
     * @param prop2 the prop2 to set
     */
    public void setProp2(String prop2) {
        this.prop2 = prop2;
    }



}

Than my bean will implement an EventListener interface and this listener will handle all setters. 比我的bean将实现EventListener接口,并且此侦听器将处理所有的setter。 In case of any setter method called (after initialization) then edited property will set to true. 如果调用了任何setter方法(初始化后),那么edited属性将设置为true。

So my question is what would be proper way to add action/event listener to handle setters? 所以我的问题是添加动作/事件侦听器以处理设置程序的正确方法是什么?

EDIT** I have tried PropertyChangeListener but didnt get any event output. 编辑**我已经尝试过PropertyChangeListener,但是没有得到任何事件输出。 And if I add each setters pcs.firePropertyChange(); 如果我添加每个设置器pcs.firePropertyChange(); method then it doesnt make sense that I can set isEdited straight true via those methods. 方法,那么通过这些方法将isEdited设置 true 毫无意义。

Can't you have a Map<String,Boolean> and update it with each setter? 您不能拥有Map<String,Boolean>并用每个设置器更新它吗? Take prop1 , for example: prop1为例:

public void setProp1(String prop1) { 
    if(!prop1.equals(this.prop1))
        updateMap.put("prop1", true);
    this.prop1 = prop1;
}

This way, while saving the entity you'll have a map with that "metadata". 这样,在保存实体的同时,您将获得一个带有“元数据”的地图。

EDIT: There's a flaw tough, because if an user sets a value and then goes back to the original the map will stay in true. 编辑:有一个缺点很难,因为如果用户设置一个值然后返回到原始,该地图将保持不变。 You can avoid that by having another map (or cloning your object) with the original values to comparate both things: 您可以通过使用另一个映射(或克隆您的对象)来使用原始值来比较两者,从而避免这种情况:

public void setProp1(String prop1) { 
    if(!prop1.equals(this.prop1) && !prop1.equals(ORIGINAL_VALUE))
        updateMap.put("prop1", true);
    else
        updateMap.put("prop1", false);
    this.prop1 = prop1;
}

EDIT: Adam is right about aspects and indeed it's a change that can cost you some time. 编辑:亚当是正确的方面,确实,这是一项更改,可能会花费您一些时间。 Also, if you want to use reflection there's another catch because you're tied to the structure of the methods. 另外,如果您想使用反射,则还有另一个问题,因为您与方法的结构有关。 In the future if you want to change a method's name or type you'll have to update that reflection-helper class too. 将来,如果您想更改方法的名称或类型,则也必须更新该反射帮助器类。

I'd suggest updating temporal values before saving them so you can compare them to the originals but that would involve changing your methods if you access the fields/object directly without a getter. 我建议在保存它们之前先更新时间值,以便您可以将它们与原始值进行比较,但是如果直接访问字段/对象而没有获取方法,那将涉及更改方法。

In the end, a third option (there's always a third) and the one I think you might be willing to do is using valueChangeListener 's in your components. 最后,第三个选项(总是有第三个选项),我认为您可能愿意做的是在组件中使用valueChangeListener For example: 例如:

<h:inputText id="prop1Input" value="#{bean.prop1}" valueChangeListener="#{bean.changesListener}"/>

And your bean should have a method with this structure: 并且您的bean应该具有一个具有以下结构的方法:

public void changesListener(ValueChangeEvent e) {
    //Get the new value
    Object o = e.getNewValue();
    //get the component's id
    String componentId = e.getComponent().getId();
    //Cast the value and compare it, after that you should update a map. You are
    //going to need one anyway to know which field changed.
    boolean valueChanged = //compare against original value
    if(componentId.equals("prop1Input"));
    map.put("prop1", valueChanged);
}

An important note about this approach, the listener will be executed during the validation phasethe. 关于此方法的重要说明,侦听器将在验证阶段执行。 The intention of this listener is to be able to handle both new and old value, which seems to be your case. 该侦听器的目的是能够处理新旧价值,这似乎是您的情况。 Since you can also know the component that fired it you should be fine. 因为您还可以知道触发它的组件,所以应该没问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM