以前很忽视 javabean ,除了写写简单的 get,set 很少用到其他,近来探索 attribute 中,回头再看 javabean 突然觉得很相似,或许 yui3 attribute正是受到了 javabean component model 的影响而产生?
PS : 这里说的不是 EJB ,from core java 2:
We'd like to address a common confusion before going any further: The JavaBeans that we discuss in this chapter have little in common with "Enterprise JavaBeans " or EJB. Enterprise JavaBeans are server-side components with support for transactions, persistence, replication, and security. At a very basic level, they too are components that can be manipulated in builder tools. However, the Enterprise JavaBeans technology is quite a bit more complex than the "Standard Edition" JavaBeans technology.
That does not mean that standard JavaBeans components are limited to client-side programming. Web technologies such as JavaServer Faces (JSF) and JavaServer Pages (JSP) rely heavily on the JavaBeans component model.
1.getter ? setter?
不像 C# 可以对属性定义 getter,setter 后以后就可以直接对属性访问进行控制,java 中还是传统的使用属性访问方法,没有提供直接访问属性控制的机制,同目前广泛实现的 ecmascript3 类似,所以 yui3 attribute 也等于是模拟了 java ,提供了 getter ,setter 用方法来控制属性访问,并类似java,c#将属性元定义定义在了 javascript 类(构造器)中,javabean getter,setter则是语言级别提供了:
public class TestAttr extends Attribute {
private String test = "5";
public String getTest() {
System.out.println("i am reading ...");
return test;
}
public void setTest(String test) {
System.out.println("i am writing");
this.test = test;
}
}
另一方面当使用继承时,java 语言层次保证了继承链上的属性初始化,而 yui3 attribute 则通过 Base 模拟了该初始化。
2. 属性变化事件的触发
yui3 attribute 通过set 封装,在设置内部属性值前后,要触发before以及after事件,并且可以通过before事件来阻止属性的真正有效写入,而javabean component model 则直接提供了 PropertyChangeSupport (用于写后通知) 与 VetoableChangeSupport (用于阻止),只不过需要在setter中手动调用,其实由于java存在反射机制,我们也可以很容易的模拟 yui3 attribute 的 set 封装:(用 beanutils 更方便)
public class Attribute {
private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
private VetoableChangeSupport vetoSupport = new VetoableChangeSupport(this);
public void addPropertyChangeListener(PropertyChangeListener listener) {
changeSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
changeSupport.removePropertyChangeListener(listener);
}
public void addVetoableChangeListener(VetoableChangeListener listener) {
vetoSupport.addVetoableChangeListener(listener);
}
public void removeVetoableChangeListener(VetoableChangeListener listener) {
vetoSupport.removeVetoableChangeListener(listener);
}
public void set(String name, Object newValue) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, PropertyVetoException {
Object oldValue = BeanUtils.getProperty(this, name);
vetoSupport.fireVetoableChange(name, oldValue, newValue);
BeanUtils.setProperty(this, name, newValue);
changeSupport.firePropertyChange(name, oldValue, newValue);
}
}
3.测试
一个很简单的例子即可验证该模式同 yui3 attribute 的相似性:
public static void main(String[] args) throws InvocationTargetException,
PropertyVetoException, NoSuchMethodException, IllegalAccessException {
TestAttr t = new TestAttr();
t.addVetoableChangeListener(new VetoableChangeListener() {
//属性真正设置前调用
public void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException {
System.out.println(evt.getNewValue());
System.out.println(evt.getOldValue());
//如果验证失败,就throw
//throw new PropertyVetoException("",null);
}
});
t.addPropertyChangeListener(new PropertyChangeListener() {
//属性设置后通知
public void propertyChange(PropertyChangeEvent evt) {
System.out.println(evt.getNewValue());
System.out.println(evt.getOldValue());
}
});
//System.out.println(t.getTest());
t.set("test", 2);
//System.out.println(t.getTest());
}
PS:
IE9 不再支持 __defineGetter__,转而支持 ES5 API , Link MSDN