用户定义的Java监听器

时间:2010-07-02 09:56:17

标签: java

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

4 个答案:

答案 0 :(得分:22)

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

让我们看一个我们可以观察的样本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);
    }
  }
}

监听器界面:

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

Observable界面:

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

和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
  }

}

修改 纠正了setter方法中的一个丑陋错误 - 现在在属性设置之后触发了事件。反过来说,副作用是,如果听众读了改变的属性,他仍然会看到旧的,不变的值...

答案 1 :(得分:6)

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

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

示例类

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);
  }
}

使用示例

// 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);

答案 2 :(得分:3)

您应该使用 Observer Design Pattern 。此模式使用以下类:

这是一个例子。

观察员:

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
        }
    }
}

可观察对象:

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
    }
}

主要课程:

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(...);
}

答案 3 :(得分:1)