Java冷门包java.beans有什么用?
前言
java.beans这个包好像很少见人提到过,看名字就知道这是有关处理java bean的,在jdk 8中一共26个类,但是能有一点点用的感觉没几个,相似的功能都可以用更好的办法解决,在网上找了半天,也没有什么有用的例子,真是糟糕的设计。
但是里面有几个类,好像还是有点用处的。
BeanDescriptor
第一个就是BeanDescriptor,但是这玩意有点迷,不知道怎么用,看名字就是对Bean的描述,我以为给他传入一个bean的class,可以从中获取到里面的字段信息,可是想错了,压根不能。
里面只有一些set/get bean名字的,默认请求下,如getDisplayName会返回传入的class名称,更谜的是,里面getValue、setValue、attributeNames方法就是对一个map的操作。
单独使用BeanDescriptor好像也没啥用处,应该在某些情况下封装中的吧。
PropertyDescriptor
这个还算有点用,是对bean 中字段的封装,比如bean中有一个String类型的字段value,通过他,可以获取到set/get的Method。
public class MyBean {
private String value="s";
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public String toString() {
return "MyBean{" +
"value='" + value + ''' +
'}';
}
}
try {
MyBean myBean = new MyBean();
PropertyDescriptor value = new PropertyDescriptor("value", MyBean.class);
Method writeMethod = value.getWriteMethod();
writeMethod.invoke(myBean, "张三");
System.out.println(myBean);
} catch (IntrospectionException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
最后来看一个好玩的,隐约觉得这个功能很有潜力,他允许你对字段get/set的时候对他进行加工,也可以看作代理,但是和代理也有点不一样。
通过PropertyDescriptor拿到指定字段的时候描述后,在对他设置一个"加工工厂"的类,这个类要继承PropertyEditor,并且一定要重写他的有参构造方法,接着通过createPropertyEditor创建这个类的实例,他的参数是目标bean的实例。
但是,最后改变的数据并不能反映到最终的bean上,虽然给了一个属性改变的通知接口,我以为会传入旧数据和新数据,其实不然,源码中全部都传入的null。只有一个参数是source,是bean的实例。
如果改变要反映的最终的bean上,那就要自己通过反射写了。
public class Main {
public static class MyStringEditor extends PropertyEditorSupport {
public MyStringEditor(Object source) {
super(source);
}
@Override
public void setValue(Object value) {
PropertyDescriptor propertyDescriptor = null;
try {
propertyDescriptor = new PropertyDescriptor("value", MyBean.class);
propertyDescriptor.getWriteMethod().invoke(getSource(), value);
} catch (IntrospectionException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
super.setAsText(text);
}
@Override
public Object getValue() {
return "新的值" + getSource();
}
}
public static void main(String[] args) throws IOException {
try {
MyBean myBean = new MyBean();
PropertyDescriptor value = new PropertyDescriptor("value", MyBean.class);
value.setPropertyEditorClass(MyStringEditor.class);
PropertyEditor propertyEditor = value.createPropertyEditor(myBean);
propertyEditor.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
System.out.println("数据改变" + evt.getSource());
}
});
propertyEditor.setValue(new String("test"));
System.out.println(myBean.getValue());
} catch (IntrospectionException e) {
e.printStackTrace();
}
}
}
try {
BeanInfo beanInfo = Introspector.getBeanInfo(MyBean.class);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
System.out.println(propertyDescriptor.getName());
}
} catch (IntrospectionException e) {
e.printStackTrace();
}
Introspector
这个类是个工具类,用来获取目标bean的信息,比如所有public方法,所有符合java bean规范的字段。
从中也可以获取到BeanDescriptor的信息。
try {
BeanInfo beanInfo = Introspector.getBeanInfo(MyBean.class);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
MethodDescriptor[] methodDescriptors = beanInfo.getMethodDescriptors();
for (MethodDescriptor methodDescriptor : methodDescriptors) {
System.out.println(methodDescriptor.getName() +" "+methodDescriptor);
}
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
System.out.println(propertyDescriptor.getName());
}
} catch (IntrospectionException e) {
e.printStackTrace();
}
- END -
原文始发于微信公众号(十四个字节):Java冷门包java.beans有什么用?