java为我们提供了两个类,分别提供对bean的绑定属性,以及约束属性的侦听功能
PropertyChangeSupport/VetoableChangeSupport
其中,绑定属性只能监听到属性的更改,却不能中断所做的操作,而约束属性可以通过抛出PropertyVetoException异常的方式阻止属性的更改
首先,定义一个javabean,在成员属性中添加PropertyChangeSupport 和VetoableChangeSupport ,并在构造方法中对其初始化
因为要监听到属性的更改,所以应该在set方法中添加触发监听器的代码
1 package javaBeanDemo; 2 3 import java.beans.PropertyChangeListener; 4 import java.beans.PropertyChangeSupport; 5 import java.beans.PropertyVetoException; 6 import java.beans.VetoableChangeListener; 7 import java.beans.VetoableChangeSupport; 8 import java.io.Serializable; 9 10 public class ProBean implements Serializable{ 11 /** 12 * 13 */ 14 private static final long serialVersionUID = 1L; 15 private String name; 16 private PropertyChangeSupport pcs; 17 private VetoableChangeSupport vcs; 18 19 public ProBean(String name) { 20 this.name = name; 21 pcs=new PropertyChangeSupport(this); 22 vcs=new VetoableChangeSupport(this); 23 } 24 25 public ProBean(){ 26 pcs=new PropertyChangeSupport(this); 27 vcs=new VetoableChangeSupport(this); 28 } 29 30 public String getName() { 31 return name; 32 } 33 34 //值被改变后,触发监听器 35 public void setName(String name) throws PropertyVetoException { 36 String oldValue=this.getName(); 37 String newValue=name; 38 // System.out.println("######SetName######"); 39 vcs.fireVetoableChange("name", oldValue, newValue); 40 this.name = name; 41 pcs.firePropertyChange("name", oldValue, newValue); 42 } 43 //监听器的添加/删除方法 44 public void addPropertyChangeListener(PropertyChangeListener Listener ){ 45 pcs.addPropertyChangeListener(Listener); 46 } 47 public void addVetoableChangeListener(VetoableChangeListener Listener){ 48 vcs.addVetoableChangeListener(Listener); 49 } 50 public void removePropertyChangeListener(PropertyChangeListener Listener ){ 51 pcs.removePropertyChangeListener(Listener); 52 } 53 public void removeVetoableChangeListener(VetoableChangeListener Listener){ 54 vcs.removeVetoableChangeListener(Listener); 55 } 56 57 58 59 }
注意,因为VetoableChangeListener拥有阻止更改的权利,所以,应该在属性值被更改前触发
vcs.fireVetoableChange("name", oldValue, newValue);
而PropertyChangeListener在属性值被更改后触发
pcs.firePropertyChange("name", oldValue, newValue);
传递的三个参数分别为:要更改的属性名,旧的值,和将要更改的值
这三个参数会被封装成一个PropertyChangeEvent对象传递给我们的listener对象(前提是该listener已经被添加为该bean的监听器)
最后,再bean中添加添加监听器和移出监听器的方法:直接调用*ChangeSupport方法中的romove和add方法即可
然后,在写用于监听bean的属性变化的监听器。由于该bean定义了两个属性(绑定/约束),所以,该监听器应该实现两个接口: implements PropertyChangeListener,VetoableChangeListener
分别实现接口中的vetoableChange和propertyChange方法
package Listener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyVetoException; import java.beans.VetoableChangeListener; public class listener implements PropertyChangeListener,VetoableChangeListener { @Override public void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException { // TODO Auto-generated method stub if(evt.getNewValue().equals("frank")) throw new PropertyVetoException("新值不能是frank", evt); } @Override public void propertyChange(PropertyChangeEvent evt) { // TODO Auto-generated method stub System.out.println("#######proChange#######"); System.out.println("新值:"+evt.getNewValue()); System.out.println("旧值"+evt.getOldValue()); } }
在vetoableChange方法中,我们定义如图更改的值为frank,则抛出异常,阻止属性的更改
而propertyChange没有更改的权利,只是把新值与旧值打印到控制台
最后写测试类:
package test; import java.beans.PropertyVetoException; import Listener.listener; import javaBeanDemo.ProBean; public class TestMain { public static void main(String[] args) { // TODO Auto-generated method stub ProBean pb=new ProBean("lee"); listener lis=new listener(); pb.addPropertyChangeListener(lis ); pb.addVetoableChangeListener(lis); try { pb.setName("fred"); pb.setName("frank"); } catch (PropertyVetoException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }