JDK 之 Java Bean 内省机制

JDK 规范目录(https://www.cnblogs.com/binarylei/p/10200503.html)

JavaBean 是一种特殊的 Java 类,主要用于传递数据信息,这种 Java 类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。

一、JavaBean

1.1 JavaBean 命名规则

  1. 一个 JavaBean 类中的方法,去掉 set 或 get 前缀,剩余部分就是属性名,如果剩余部分的第二个字母是小写的,则把剩余部分的首字母改成小的。

    getAge/setAge --> age

    gettime --> time

    setTime --> time

  2. 如果去掉前缀,剩余部分的第二个字母为大写,则全部大写

    getCPU --> getCPU

1.2 什么叫做内省?

Java 内省主要使用来对 JavaBean 进行操作的,所以当一个类满足了 JavaBean 的条件,就可以使用内省的方式来获取和操作 JavaBean 中的字段值。内省提供了操作 JavaBean 的 API。

Java 中提供了一套 API 用来访问某个属性的 getter/setter 方法,通过这些 API 可以使你不需要了解这个规则,这些 API 存放于包 java.beans 中,一般的做法是通过类 Introspector 的 getBeanInfo 方法 来获取某个对象的 BeanInfo 信息,然后通过 BeanInfo 来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后我们就可以通过反射机制来调用这些方法。

二、JDK 内省机制

2.1 Introspector 类

Introspector 这个类位于 java.beans 包中,该类中的方法都是静态的,可以直接使用类名调用。

// 获取 beanClass 及其所有父类的 BeanInfo
BeanInfo getBeanInfo(Class<?>beanClass) // 获取 beanClass 及其指定到父类 stopClass 的 BeanInfo
BeanInfo getBeanInfo(Class<?> beanClass, Class<?> stopClass)

我们可以使用 Introspector 的 getBeanInfo(Class<?> beanClass) 来获取一个 JavaBean 类的 BeanInfo 对象。BeanInfo 有三个常用的属性:

// bean 信息
BeanDescriptor beanDescriptor = beanInfo.getBeanDescriptor();
// 属性信息
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
// 方法信息
MethodDescriptor[] methodDescriptors = beanInfo.getMethodDescriptors();

2.2 PropertyDescriptor 类

这个类位于 java.beans 包中。

@Test
public void test() throws Exception {
PropertyDescriptor pd = new PropertyDescriptor("id", User.class);
System.out.println(pd.getName());
}

2.3 PropertyEditor 类

Spring 中使用 PropertyEditor 向 JavaBean 中注入属性。

@Test
public void test1() throws Exception {
User user = new User(); PropertyDescriptor propertyDescriptor = new new PropertyDescriptor("id", User.class);
propertyDescriptor.setPropertyEditorClass(IntPropertyEditor.class);
PropertyEditor propertyEditor = propertyDescriptor.createPropertyEditor(user); propertyEditor.setAsText("99");
Method writeMethod = propertyDescriptor.getWriteMethod();
writeMethod.invoke(user, propertyEditor.getValue()); System.out.println(user);
} @Test
public void test2() throws Exception {
User user = new User(); PropertyDescriptor propertyDescriptor = new new PropertyDescriptor("id", User.class);
propertyDescriptor.setPropertyEditorClass(IntPropertyEditor.class);
PropertyEditor propertyEditor = propertyDescriptor.createPropertyEditor(user); // 这个 evt 实际上就是 propertyEditor 对象
propertyEditor.addPropertyChangeListener(evt -> {
PropertyEditor source = (PropertyEditor) evt.getSource();
Method writeMethod = propertyDescriptor.getWriteMethod();
writeMethod.invoke(user, source.getValue());
});
propertyEditor.setAsText("99");
System.out.println(user);
} // JDK 中的 PropertyEditor 接口
public static class IntPropertyEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
setValue(Integer.parseInt(text));
}
}

三、Apache BeanUtils 工具包

Apache 组织开发了一套用于操作 JavaBean 的 API(内省)。该工具在 commons-beanutils 包中,核心类 BeanUtils:

setProperty(bean, name, value)
copyProperties(target, source)

可以支持 String 到 8 中基本数据类型转换,其他引用数据类型都需要注册转换器 ConvertUtils.register(Converter, Class)

使用 BeanUtils 来格式化日期:

public static void main(String[] args) throws Exception {

    User user = new User();

    String name = "zhangsan";
String birthday = "19801122"; // 注册一个转换器
/* 使用匿名内部类来注册转换器
ConvertUtils.register(new Converter() { public Object convert(Class beanClass, Object value) {
String birthday = (String) value;
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
try {
return sdf.parse(birthday);
} catch (ParseException e) {
return null;
}
}
}, Date.class);
*/ DateConverter converter = new DateConverter();
converter.setPatterns(new String[]{"yyyy-MM-dd","yyyyMMdd","MM/dd/yyyy"});
ConvertUtils.register(converter, Date.class); BeanUtils.setProperty(user, "name", name);
BeanUtils.setProperty(user, "birthday", birthday); System.out.println(user);
}

参考:

  1. 《JavaBean 以及内省技术详解》:https://www.cnblogs.com/yejiurui/archive/2012/10/06/2712693.html

每天用心记录一点点。内容也许不重要,但习惯很重要!

最新文章

  1. linux下安装Redis以及phpredis模块
  2. 【腾讯Bugly干货分享】基于RxJava的一种MVP实现
  3. 控制Arduino的利器-Windows Remote Arduino
  4. PHP常量、变量作用域详解(一)
  5. go json null字段的转换
  6. ImageView显示网络图片
  7. eclipse默认文件编码
  8. 对指定文件生成数字摘要的MD5工具类
  9. Less 关于css hack的写法
  10. window.open()提交POST数据
  11. php中mysql语句的基本写法
  12. jsf小例子
  13. python 字典的常见操作
  14. 101210-450789-147200(可以激活Xshell5,而且可以升级) 亲测可用 只能用于xshell5
  15. jmeter4.x centos7部署笔记
  16. windows 创建共享文件夹
  17. js和JQuery区别
  18. api日常总结
  19. 试一下Markdown
  20. (mysql数据库报错)The user specified as a definer (&#39;root&#39;@&#39;%&#39;) does not exist

热门文章

  1. table-cell http://www.cnblogs.com/StormSpirit/archive/2012/10/24/2736453.html
  2. 修改.net反编译的dll
  3. Redis备份及回收策略
  4. 批量执行命令(SSH)
  5. Shc 应用
  6. 最小k度限制生成树
  7. FPGA功耗那些事儿(转载)
  8. Python+Selenium学习--定位一组对象
  9. cross-env:跨平台设置和使用环境变量
  10. SSM提交了事物但数据库不执行