Java冷门包java.beans有什么用?

>>强大,10k+点赞的 SpringBoot 后台管理系统竟然出了详细教程!

前言

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有什么用?