java中类的实例化对象的属性值是经常发生变化的,有时候我们需要监听到对象中属性值的变化,从而触发额外的操作,举个栗子:我们日常开发的项目上线后一般都会有监控,拿cpu监控来说,如果系统访问量达到了一天中的峰值,这时候会监控到cpu使用率超过了80%,这个时候我们就需要采取措施,不然就可能出现系统瘫痪风险。今天要说的是java提供的一个功能 属性监听,最重要的就是PropertyChangeListener,接下来将通过实例来展示其功能和使用方式
PropertyChangeListener是一个接口,源码如下:
/**
* A "PropertyChange" event gets fired whenever a bean changes a "bound"
* property. You can register a PropertyChangeListener with a source
* bean so as to be notified of any bound property updates.
*/
public interface PropertyChangeListener extends java.util.EventListener {
/**
* This method gets called when a bound property is changed.
* @param evt A PropertyChangeEvent object describing the event source
* and the property that has changed.
*/
void propertyChange(PropertyChangeEvent evt);
}
可以看到,该接口继承了EventListener(空接口)接口,并且只有一个方法propertyChange,该方法的作用就是被监听的对象属性发生变化后触发事件,改方法的实现类去做具体的业务逻辑
该类使用PropertyChangeListenerMap(底层是一个Map)管理一个监听器列表,根据如下源码可以发现,其主要提供了一些增加,获取,移除和触发监听器的操作方法.
我们定义一个人类Person,一个体重属性weight,然后定义一个监听器监听器属性变化(比如,体重变大,提醒需要减肥了,如果体重变轻,提醒需要补充营养了),具体实现如下:
package com.typhoon.spring_jdbctemplate.listener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
/**
* 人类
*
* @author Typhoon
*
*/
public class Person {
private int weight;//kg
public Person(int weight) {
super();
this.weight = weight;
}
//创建当前对象的事件监听管理器
PropertyChangeSupport listeners = new PropertyChangeSupport(this);
public int getWeight() {
return weight;
}
/**
* 设置属性的时候触发监听器
*
* @param weight
*/
public void setWeight(int weight) {
this.firePropertyChange("weight", this.weight, weight);
//this.weight = weight;//为了测试,只触发不实际修改
}
/**
* 监听管理器为当前对象添加监听
*
* @param listener
*/
public void addPropertyChangeListener(PropertyChangeListener listener) {
this.listeners.addPropertyChangeListener(listener);
}
/**
* 管理器当前对象的管理器
*
* @param listener
*/
public void removePropertyChangeListener(PropertyChangeListener listener) {
this.listeners.removePropertyChangeListener(listener);
}
}
上述代码定义了类Person,并且增加了新增和触发监听器等方法
定义监听器:
/**
* Person对象属性监听器
*
* @author Typhoon
*
*/
public class PersonPropertyListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent event) {
System.out.println("propertyName:" + event.getPropertyName() + ",\n oldeValue:" + event.getOldValue() + "\n newValue:" + event.getNewValue());
if("weight".equals(event.getPropertyName())) {//
int oldValue = (int) event.getOldValue();
int newValue = (int) event.getNewValue();
if(oldValue > newValue ) {//体重变轻
System.out.println("请注意增加营养!");
} else if(oldValue < newValue) {//变重
System.out.println("该减肥了,请加强锻炼!");
} else if(oldValue == newValue) {
System.out.println("身材保持不错,加油!");
}
}
}
}
编写测试类:
public class TestMain {
public static void main(String[] args) {
Person p = new Person(65);
//添加监听器
p.addPropertyChangeListener(new PersonPropertyListener());
p.setWeight(64);
p.setWeight(65);
p.setWeight(66);
}
}
运行测试类,得到如下结果:
可以看到,我们似乎已经得到想要接的过,但是细心的人会发现,代码中有三次set操作,也就是说理论上会触发三次监听器,多次运行后结果没有发生变化,但是为什么又一次没有触发呢?我们还是从java源码分析,我们代码中触发监听器操作本质上操作的是下述代码:
this.listeners.firePropertyChange(propertyName, oldValue, newValue);
跟踪到源码中我们可以看到:
可以看出只有oldValue == null || newValue == null || !oldValue.equals(newValue)时才会触发操作,而我们的例子中Person的weight属性初始化为65,p.setWeight(65)操作不满足!oldValue.equals(newValue)条件,这才是症结所在,也就是说我们在修改属性的时候如果新值和旧值相等的话并不会触发监听器.
其实这是java中一种典型的观察者模式,通过为业务类注册监听器,在业务类实例属性发生变化的时候触发监听器来完成其他业务;任何一个存在的事物都有有弊有利,使用PropertyChangeListener的优缺点如下:
但是对于此功能,整体看来是利大于弊的,希望各位看官在业务中有所使用并发现其优劣.
PS:原创不易,多多支持!
本文分享自 PersistentCoder 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!