Commons BeanUtils 用户指南

具体参考自:Commons BeanUtils1.9.3帮助文档

对大多数开发场景来说非常重要的JavaBeans所需的特性:

  • 类必须是public,并提供一个public的无参构造函数。
  • 属性名以小写字母开头。
  • 每个bean属性都有一个公共gettersetter方法,方法的命名方式是使用getset作为前缀其后紧跟属性名,而属性名的第一个字符要大写。【约定而不是规定】
  • 布尔类型的属性可以使用is作为前缀,而不是get前缀来命名getter方法,这样更容易理解。
  • 属性的getter方法返回的数据类型必须与setter方法接受的数据类型匹配。如果有多个具有相同名称但属性类型不同的setter,这与JavaBeans规范是背道而驰的。
  • 不需要为每个属性提供一个gettersetter方法。
  • JavaBeans规范描述了许多超出BeanUtils包范围的特性,包含用于事件监听的附加设计模式,wiring JavaBeans together into component hierarchies【不太理解】,等等。

Common-Beanutils包要有如下两个依赖:

标准 JavaBean

The APIs in the BeanUtils package are intended to simplify getting and setting bean properties dynamically, where the objects you are accessing – and the names of the properties you care about – are determined
at runtime in your application, rather than as you are writing and compiling your application’s classes.

BeanUtils旨在简化动态获取和设置bean属性,bean中的属性名称是在程序运行时确定的,而不是在编写和编译应用程序的类时确定的。【翻译待确定】

JavaBean支持的可能属性类型可以分为三类 – 其中一些由标准JavaBeans规范支持,而其中一些由BeanUtils包唯一支持:

  • Simple【简单】 - 简单属性仅包含一个可以检索或修改的值。底层的属性类型可以是Java的基本类型(例如int,简单的对象如java.lang.String),或者是更加复杂的对象。
  • Indexed【索引】 - 索引属性存储着一个有序的对象集合(所有类型相同),这些对象可以被非负的整型索引(或下标)单独访问。Alternatively, the entire set of values may be set or retrieved using an array。作为JavaBeans规范的扩展,BeanUtils包也考虑将其底层数据类型为java.util.List(或List的实现)的任何属性也编入索引。
  • Mapped【映射】 - 作为对标准JavaBeans API的扩展,the BeanUtils package considers any property whose underlying value is a java.util.Map to be “mapped”. 你可以通过字符串值键设置和检索单个值。

PropertyUtils类中提供了各种API方法来获取和设置所有这些类型的属性值。在下面的代码片段中,假设有两个使用以下方法签名定义的bean类:

public class Employee {
    public Address getAddress(String type);
    public void setAddress(String type, Address address);
    public Employee getSubordinate(int index);
    public void setSubordinate(int index, Employee subordinate);
    public String getFirstName();
    public void setFirstName(String firstName);
    public String getLastName();
    public void setLastName(String lastName);
}

基本属性访问

获取和设置简单的(simple )属性值是非常简单,可以使用如下两个方法:

使用这些方法,您可以在应用程序中动态地操作员工的姓名:

Employee employee = ...;
String firstName = (String)PropertyUtils.getSimpleProperty(employee, "firstName");
String lastName = (String)PropertyUtils.getSimpleProperty(employee, "lastName");
... 操纵值 ...
PropertyUtils.setSimpleProperty(employee, "firstName", firstName);
PropertyUtils.setSimpleProperty(employee, "lastName", lastName);

对于indexed属性你可以有两种选择 - 你可以使用方括号为“属性名”字符串构建下标,也可以在方法调用的单独参数中指定下标:

在向属性名添加下标时,只允许使用整数常量。如果需要计算要检索的条目的索引,可以使用字符串连接来组装属性名表达式。【用字符串拼接的方式明显复杂,推荐使用第二种】【这种操作获得的不是Bean的属性,而是Bean属性的其中索引所指定的元素值】

例如,您可以执行以下任一操作:

Employee employee = ...;
int index = ...;
String name = "subordinate[" + index + "]";
Employee subordinate = (Employee)PropertyUtils.getIndexedProperty(employee, name);

Employee employee = ...;
int index = ...;
Employee subordinate = (Employee)PropertyUtils.getIndexedProperty(employee, "subordinate", index);

indexed属性操作类同,也包含两种获取和设置mapped属性的方式。区别在于额外的参数有括号而不是方括号包围,并且其包含字符串类型的键来获取和设置适当的值。

例如,您可以用以下两种方式之一设置员工的家庭地址:

Employee employee = ...;
Address address = ...;
PropertyUtils.setMappedProperty(employee, "address(home)", address);

Employee employee = ...;
Address address = ...;
PropertyUtils.setMappedProperty(employee, "address", "home", address);

嵌套属性访问

传统的写法:

String city = employee.getAddress("home").getCity();

PropertyUtils类提供了等效机制称为 nested property access【嵌套属性访问】。要使用这种方法,您可以使用“.”分隔符将访问路径的属性名称连接在一起 – 非常类似于在JavaScript中执行嵌套属性访问的方式。

与传统的Java表达式等价的PropertyUtils方法:

String city = (String)PropertyUtils.getNestedProperty(employee, "address(home).city");

最后,为了方便起见,PropertyUtils提供方法签名,使用任意嵌套级别接受任何简单、索引和映射属性访问的任意组合。

Employee employee = ...;
String city = (String) PropertyUtils.getProperty(employee,"subordinate[3].address(home).city");

定制内省

Customizing Introspection【当前无此需求,暂略过】

From version 1.9.0 onwards, BeanUtils supports customization of its introspection mechanism. This allows an application to extend or modify the default discovery of bean properties.

Suppressing Properties

【不懂,暂略过】

动态Bean (DynaBeans)

前面讲述的PropertyUtils 类提供了对现有JavaBean类的动态属性访问,而不以任何方式修改它们。动态属性访问的不同用例是,将一组动态计算的属性值表示为JavaBean,但不必实际编写Java类来表示这些属性。除了不必创建和维护单独的Java类所节省的精力外,这种能力还意味着你可以处理你所关心的属性集是动态确定的情况(考虑将SQL SELECT的结果集表示为一组JavaBean)。

为了支持这个用例,BeanUtils包提供DynaBean接口,该接口必须由实际实现接口方法的bean类实现,而关联的DynaClass接口定义特定一组DynaBeans支持的属性集,其方式与java.lang.Class定义特定JavaBean类的所有实例所支持的属性集的方式大致相同。

例如,上面示例中使用的Employee类可以实现为DynaBean,而不是作为标准JavaBean。您可以像这样访问它的属性:

DynaBean employee = ...;// Details depend on which DynaBean implementation you use
String firstName = (String) employee.get("firstName");
Address homeAddress = (Address) employee.get("address", "home");
Object subordinate = employee.get("subordinate", 2);

需要注意的一个非常重要的方便特性是: the PropertyUtils property getter and setter methods understand how to access properties in DynaBeans.因此,如果你作为第一个参数传递给PropertyUtils.getSimpleProperty()的bean实际上是DynaBean实现,则调用将透明地转换为适当的DynaBean getter方法。因此,如果你愿意,可以将应用程序的动态属性访问完全基于PropertyUtils API,并使用它们访问标准JavaBeansDynaBeans,而不必事先考虑如何实现特定bean。

因为DynaBeanDynaClass是接口,因此可以多次以不同的方式实现它们,以解决不同的使用场景。下面的小节描述了作为标准BeanUtils包的一部分提供的实现,尽管我们鼓励您在标准实现不够的情况下提供自己的自定义实现。

BasicDynaBean 和BasicDynaClass

BasicDynaBeanBasicDynaClass 的实现提供了一组基本的动态属性功能,你希望在其中动态定义属性集(由DynaProperty的实例描述)。首先定义DynaClass,该类建立您所关心的属性集:

DynaProperty[] props = new DynaProperty[]{
    new DynaProperty("address", java.util.Map.class),
    new DynaProperty("subordinate", mypackage.Employee[].class),
    new DynaProperty("firstName", String.class),
    new DynaProperty("lastName",  String.class)
};
BasicDynaClass dynaClass = new BasicDynaClass("employee", null, props);

注意,dynaBeanClass参数(在BasicDynaClass的构造函数中)可以具有NULL的值。在本例中,dynaClass.getDynaBeanClass的值将只是BasicDynaBean的类。

接下来,使用该DynaClassnewInstance()方法创建符合该DynaClass的新DynaBean实例,并填充其初始属性值(就像实例化一个新的标准JavaBean,然后调用其属性设置程序一样):

DynaBean employee = dynaClass.newInstance();
employee.set("address", new HashMap());
employee.set("subordinate", new mypackage.Employee[0]);
employee.set("firstName", "Fred");
employee.set("lastName", "Flintstone");

注意,DynaBean类被声明为DynaBean,而不是BasicDynaBean。通常,如果你使用DynaBeans,您将不必关心正在使用的实际实现类 – 只需关心声明它是DynaBean,以便你可以使用DynaBean API。

如上所述,您可以将DynaBean实例作为第一个参数传递给PropertyUtils方法,该方法将获取和设置属性,并将按你的预期进行解释 – DynaBean的动态属性将被检索或修改,而不是实际BasicDynaBean实现类上的底层属性。

ResultSetDynaClass (包装ResultSet到DynaBeans)

DynaBean API的一个非常常见的用例是包装其他通常不以JavaBeans形式呈现的”stuff【原料】”集合。最常见的需要包装的集合就是JDBC驱动程序执行行SQLSELECT语句时返回的java.sql.ResultSet。Commons BeanUtils提供了一种标准机制,用于将结果集的每一行作为DynaBean显示,如本例所示:

Connection conn = ...;
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select account_id, name from customers");
Iterator rows = (new ResultSetDynaClass(rs)).iterator();
while (rows.hasNext()) {
    DynaBean row = (DynaBean) rows.next();
    System.out.println("Account number is " + row.get("account_id") + " and name is " + row.get("name"));
}
rs.close();
stmt.close();

RowSetDynaClass (Disconnected ResultSet as DynaBeans)

》》》》》》》》后期再具体看吧!

猜你喜欢

转载自blog.csdn.net/fanxiaobin577328725/article/details/81973918