Java:在Bean中使用PropertyChangeSupport支持PropertyChangeListeners

简介:
JavaBean的属性与一般Java程序中所指的属性,或者说与所有面向对象的程序设计语言中对象的属性是一个概念,在程序中的具体体现就是类中的变量。在JavaBean的设计中,按照属性的不同作用又细分为四类:单值属性;索引属性;关联属性;限制属性。
本文主要介绍如何使用PropertyChangeSupport类来支持关联属性事件的触发。
1.关联属性
关联属性,也称之为绑定属性。绑定属性会在属性值发生变化时,通知所有相关的监听器。为了实现一个绑定属性,必须实现两个机制。
1)  无论何时,只要属性的值发生变化,该bean必须发送一个PropertyChange事件给所有已注册的监听器。该变化可能发生在调用set方法时,或者程序的用户做出某种动作时。
2)  为了使感兴趣的监听器能够进行注册,bean必须实现以下两个方法:
void  addPropertyChangeListener(PropertyChangeListener listener);
void  removePropertyChangeListener(PropertyChangeListener listener);
2.使用PropertyChangeSupport管理监听器
可以通过java.bean包下的PropertyChangeSupport类来管理监听器。要使用这个类,bean必须有一个此类的数据域。
private  PropertyChangeSupport  changes  =  new  PropertyChangeSupport( this );
 
这样就可以将添加和移除监听器的任务交给这个对象。
public   void  addPropertyChangeListener(PropertyChangeListener listener) {
     changes .addPropertyChangeListener(listener);
}
 
public   void  removePropertyChangeListener(PropertyChangeListener listener) {
     changes .removePropertyChangeListener(listener);
}
 
bean的属性发生变化时,使用PropertyChangeSupport对象的firePropertyChange方法,它会将一个事件发送给所有已经注册的监听器。该方法有三个参数:属性的名字、旧的值以及新的值。属性的值必须是对象,如果是简单数据类型,则必须进行包装。
changes .firePropertyChange( "ourString" , oldString, newString);
 
所有注册的监听器实现PropertyChangeListener接口,该接口中只有一个方法。
public   void  propertyChange(PropertyChangeEvent e);
bean的属性值发生变化时,该方法中的代码就会被触发。可以通过
e.getOldValue();
e.getNewValue();
来得到changes.firePropertyChange("ourString", oldString, newString);中的oldStringnewString
3.为什么要使用PropertyChangeSupport
使用这个类管理监听器的好处是,它是线程安全的。如果使用一个循环体来set Bean的属性,则这个类可以保证所有监听器执行触发事件的有序。
还有一个好处是,这个类支持fire带索引的属性改变事件(详见java.bean.IndexedPropertyChangeEvent)。此时向注册的监听器发送一个PropertyChangeEvent的方法为:
void  fireIndexedPropertyChange(String PropertyName, int  index,Object oldValue,Object newValue);
4.示例
MyBoundBean(具体代码见附件)是一个JavaBean,我们关注它的唯一一个属性ourString的变化情况,它的初始值是Hello。并通过PropertyChange类来管理监听器。注意在set方法中会调用firePropertyChange方法。
MyBoundBean.java
import  java.beans.PropertyChangeListener;
import  java.beans.PropertyChangeSupport;
 
public   class  MyBoundBean {
    String  ourString  =  "Hello" ;
 
     private  PropertyChangeSupport  changes  =  new  PropertyChangeSupport( this );
 
     public   void  setString(String newString) {
       String oldString =  ourString ;
        ourString  = newString;
        changes .firePropertyChange( "ourString" , oldString, newString);
    }
 
     public  String getString() {
        return   ourString ;
    }
 
     public   void  addPropertyChangeListener(PropertyChangeListener listener) {
        changes .addPropertyChangeListener(listener);
    }
 
     public   void  removePropertyChangeListener(PropertyChangeListener listener) {
        changes .removePropertyChangeListener(listener);
    }
}
 
MyCallBound1类(具体代码见附件)是它的一个监听器。整个动作是这样的,点击jButton1jButton2会触发Buttonaction事件,将jButton1test设置为文本框中的内容,同时,目标beanourString属性的内容也会设置为文本框中的内容。
MyBoundBean  b  =  new  MyBoundBean();
public   void  actionPerformed(ActionEvent e) {
     jButton1 .setText( textBox .getText());
     b .setString( textBox .getText());
}
 
目标bean的属性一改变(注意,初始值是"Hello"),将会触发propertyChange方法的执行。将文本框的内容设置为目标beanourString属性的旧值,同时,将jButton2test设置成目标beanourString属性的新值。
public   void  propertyChange(PropertyChangeEvent e) {
     if  (e.getSource() ==  b ) {
        textBox .setText(e.getOldValue().toString());
        jButton2 .setText(e.getNewValue().toString());
    }
}
 
 
如果不实现PropertyChangeListener接口的话,可以使用匿名内部类来达到同样的效果。(具体代码见附件MyCallBound2.java
MyBoundBean  b  =  new  MyBoundBean();
b .addPropertyChangeListener( new  PropertyChangeListener() {
     public   void  propertyChange(PropertyChangeEvent e) {
        //  这样一来,我们就可以用自己定义的名字实现事件
       ourString_propertyChange(e);
    }
});
 
这样一来,我们就可以用自己定义的名字实现事件。
void  ourString_propertyChange(PropertyChangeEvent e) {
     if  (e.getSource() ==  b ) {
        textBox .setText(e.getOldValue().toString());
        jButton2 .setText(e.getNewValue().toString());
    }
}

本文转自zhangjunhd51CTO博客,原文链接:http://blog.51cto.com/zhangjunhd/36838,如需转载请自行联系原作者
相关文章
|
7月前
|
搜索推荐 Java 开发者
org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException 问题处理
【5月更文挑战第14天】org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException 问题处理
661 1
|
4月前
|
Java Spring 容器
Java SpringBoot 中,动态执行 bean 对象中的方法
Java SpringBoot 中,动态执行 bean 对象中的方法
41 0
|
4月前
|
Java Spring
Java SpringBoot Bean InitializingBean 项目初始化
Java SpringBoot Bean InitializingBean 项目初始化
55 0
|
5月前
|
存储 前端开发 Java
Java中的不同Bean作用域
【7月更文挑战第5天】
59 0
Java中的不同Bean作用域
|
6月前
|
Java 持续交付 Maven
Java报错:Missing ServletWebServerFactory bean,如何解决
Java开发中遇到`Missing ServletWebServerFactory bean`错误?该问题可能由依赖冲突、配置问题或环境不一致引起。解决方法包括:检查依赖版本一致性、修复配置错误、确保环境匹配,以及查看IDE中的JRE配置。预防这类问题,可采用版本管理工具、CI/CD流程、代码审查和社区学习。木头左提醒,记得点赞和分享,下次见!
Java报错:Missing ServletWebServerFactory bean,如何解决
|
6月前
|
Java API 数据处理
Java Bean参数验证:深入探索javax.validation.constraints注解
Java Bean参数验证:深入探索javax.validation.constraints注解
207 0
|
7月前
|
消息中间件 安全 Java
在Spring Bean中,如何通过Java配置类定义Bean?
【4月更文挑战第30天】在Spring Bean中,如何通过Java配置类定义Bean?
99 1
|
7月前
|
Java 测试技术 Spring
|
Java Spring
【Java】Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean
【Java】Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean
213 0
|
前端开发 Java 数据处理
每日一道面试题之介绍一下Java Bean并谈谈它的命名规范~
每日一道面试题之介绍一下Java Bean并谈谈它的命名规范~
205 0