用户定义的 Java 监听器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3164716/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 00:38:39  来源:igfitidea点击:

User defined Listener in Java

java

提问by Manoj

In my web app, during some change over the object, i need to send a mail about the changes happened in the object. My question is how to write a listener for this. Please give me some article regarding this. Thanks

在我的 Web 应用程序中,在对象的某些更改期间,我需要发送有关对象中发生的更改的邮件。我的问题是如何为此编写一个监听器。请给我一些关于此的文章。谢谢

回答by Andreas Dolk

A typical implementation could be like this: your object is observable. So every time, one of the (observed) values changes, an event is fired and all registered listeners are notified. One of those listeners now would be designed to take the notification and create and send an EMail (Java Mail API)

一个典型的实现可能是这样的:你的对象是可观察的。因此,每次(观察到的)值之一发生变化时,都会触发一个事件并通知所有注册的侦听器。这些侦听器之一现在将被设计为接收通知并创建和发送电子邮件(Java Mail API)

Let's take a sample bean which we make observable:

让我们以一个可观察的示例 bean 为例:

public class Bean implements Observable{

  // code to maintain listeners
  private List<Listener> listeners = new ArrayList<Listener>();
  public void add(Listener listener) {listeners.add(listener);}
  public void remove(Listener listener) {listeners.remove(listener);}

  // a sample field
  private int field;
  public int getField() {return field;}
  public int setField(int value) {
    field = value;
    fire("field");        
  }

  // notification code
  private void fire(String attribute) {
    for (Listener listener:listeners) {
      fieldChanged(this, attribute);
    }
  }
}

The Listener interface:

监听器界面:

public interface Listener {
  public void fieldChanged(Object source, String attrbute);
}

The Observable interface:

可观察接口:

public interface Observable {
  public void add(Listener listener);
  public void remove(Listener listener);
}

And the EMailer:

和电子邮件:

public class Sender implements Listener {

  public void register(Observable observable) {observable.add(this);}
  public void unregister(Observable observable) {observable.remove(this);}

  public void fieldChanged(Object source, String attribute) {
    sendEmail(source, attribute); // this has to be implemented
  }

}

EDITCorrected an ugly mistake in the setter method - now the event is fired afterthe property has been set. Was the other way round, with the side effect, that if a listener read the changed property, he still saw the old, unchanged value...

编辑更正了 setter 方法中的一个丑陋的错误 - 现在在设置属性触发事件。反之亦然,副作用是,如果侦听器读取更改的属性,他仍然看到旧的、未更改的值......

回答by Adamski

If you simply wish to know about the properties of an object being modified I would recommend using a PropertyChangeListener. That way you can use the PropertyChangeSupportutility class to manage your listener instances and the firing of events. You also avoid reinventing the wheel.

如果您只是想了解正在修改的对象的属性,我建议您使用PropertyChangeListener. 这样您就可以使用PropertyChangeSupport实用程序类来管理您的侦听器实例和事件的触发。您还可以避免重新发明轮子。

For more bespoke event firing I would recommend defining your own listener interface.

对于更多定制的事件触发,我建议定义您自己的侦听器接口。

Example Class

示例类

public class MyBean {
  private final PropertyChangeSupport support;

  private int i;
  private boolean b;

  public MyBean() {
    this.support = new PropertyChangeSupport(this);
  }

  // Accessors and Mutators.  Mutating a property causes a PropertyChangeEvent
  // to be fired.
  public int getI() { return i; }

  public void setI(int i) {
    int oldI = this.i;
    this.i = i;
    support.firePropertyChange("i", oldI, this.i);
  }

  public boolean getB() { return b; }

  public void setB(boolean b) {
    boolean oldB = this.b;
    this.b = b;
    support.firePropertyChange("b", oldB, this.b);
  }

  // Wrapper methods that simply delegate listener management to
  // the underlying PropertyChangeSupport class.
  public void addPropertyChangeListener(PropertyChangeListener l) {
    support.addPropertyChangeListener(l);
  }

  public void addPropertyChangeListener(String propertyName, PropertyChangeListener l) {
    // You would typically call this method rather than addPropertyChangeListener(PropertyChangeListener)
    // in order to register your listener with a specific property.
    // This then avoids the need for large if-then statements within your listener
    // implementation in order to check which property has changed.

    if (!"i".equals(propertyName) && !"b".equals(propertyName)) {
      throw new IllegalArgumentException("Invalid property name: " + propertyName);
    }

    support.addPropertyChangeListener(propertyName, l);
  }

  public void removePropertyChangeListener(PropertyChangeListener l) {
    support.removePropertyChangeListener(l);
  }

  public void removePropertyChangeListener(String propertyName, PropertyChangeListener l) {
    support.removePropertyChangeListener(propertyName, l);
  }
}

Example Usage

示例用法

// Create a new instance of our observable MyBean class.
MyBean bean = new MyBean();

// Create a PropertyChangeListener specifically for listening to property "b".
PropertyChangeListener listener = new PropertyChangeListener() {
  public void propertyChange(PropertyChangeEvent evt) {
    assert "b".equals(evt.getPropertyName());
    boolean oldB = (Boolean) evt.getOldValue();
    boolean newB = (Boolean) evt.getNewValue();

    System.err.println(String.format("Property b updated: %b -> %b, oldB, newB));
  }
}

// Register listener with specific property name.  It will only be called back
// if this property changes, *not* the "i" int property.
bean.addPropertyChangeListener("b", listener);

回答by ToYonos

You should use the Observer Design Pattern. This pattern uses these classes :

您应该使用观察者设计模式。此模式使用这些类:

Here is an example.

这是一个例子。

The observer :

观察员:

public class EmailObserver implements Observer
{
    @Override
    public void update(Observable obj, Object arg)
    {
        if (obj instanceof YourObject)
        {
            // TODO Send the mail or whatever, you have access to the modified object through obj
            // In arg you can put some additional parameter, like the modified field
        }
    }
}

The Observable Object :

可观察对象:

public static class YourObject extends Observable
{
    public void setSomething(Object parameter)
    {
        // TODO some modification in YourObject

        setChanged(); // From Observable : the object has changed
        notifyObservers(parameter); // Notify the observer about the change
    }
}

And the main class :

和主类:

public static void main(String[] args)
{
    // Create YourObject
    YourObject o = new YourObject();

    // create an observer
    EmailObserver emailObserver = new EmailObserver();

    // subscribe the observer to your object
    o.addObserver(emailObserver);

    // Now you can modify your object, changes will be notified by email
    o.setSomething(...);
}