(java 往日的翻译) commons-beanutils 第一,二章

发布时间: 2008-05-04 12:18:00

1.Overview 概述

1.1 Background 背景

The JavaBeans name comes from a Java API for a component architecture for the Java language. Writing Java classes that

conform to the JavaBeans design patterns makes it easier for Java developers to understand the functionality provided by

your class, as well as allowing JavaBeans-aware tools to use Java's introspection capabilities to learn about the properties

and operations provided by your class, and present them in a visually appealing manner in development tools.



The JavaBeans Specification describes the complete set of characteristics that makes an arbitrary Java class a JavaBean or

not -- and you should consider reading this document to be an important part of developing your Java programming skills.

However, the required characteristics of JavaBeans that are important for most development scenarios are listed here:

JavaBean规范 描述了一组特性的集合,这些特性决定了任意一个类是否是JavaBean. --你应当把读这个文档(意指JavaBean规范)作为发展


# The class must be public, and provide a public constructor that accepts no arguments. This allows tools and applications

to dynamically create new instances of your bean, without necessarily knowing what Java class name will be used ahead of

time, like this:


String className = ...;
Class beanClass = Class.forName(className);
Object beanInstance = beanClass.newInstance();

# As a necessary consequence of having a no-arguments constructor, configuration of your bean's behavior must be

accomplished separately from its instantiation. This is typically done by defining a set of properties of your bean, which

can be used to modify its behavior or the data that the bean represents. The normal convention for property names is that

they start with a lower case letter, and be comprised only of characters that are legal in a Java identifier.



# Typically, each bean property will have a public getter and setter method that are used to retrieve or define the

property's value, respectively. The JavaBeans Specification defines a design pattern for these names, using get or set as

the prefix for the property name with it's first character capitalized. Thus, you a JavaBean representing an employee might

have (among others) properties named firstName, lastName, and hireDate, with method signatures like this:

典型的特点是,每个属性都会有一个public的getter, setter方法,我们可以分别用它们进行查询或者设置对应属性的值。 JavaBeans规范定


某个代表了employee的JavaBean 也许会有 firstName, lastName, hireDate 这样的属性名, 它们的方法名是:
public class Employee {
public Employee(); // Zero-arguments constructor
public String getFirstName();
public void setFirstName(String firstName);
public String getLastName();
public void setLastName(String lastName);
public Date getHireDate();
public void setHireDate(Date hireDate);
public boolean isManager();
public void setManager(boolean manager);
public String getFullName();

# As you can see from the above example, there is a special variant allowed for boolean properties -- you can name the

getter method with a is prefix instead of a get prefix if that makes for a more understandable method name.


# If you have both a getter and a setter method for a property, the data type returned by the getter must match the data

type accepted by the setter. In addition, it is contrary to the JavaBeans specification to have more than one setter with

the same name, but different property types.

如果某个属性同时有个getter和setter方法,那么 getter返回的类型,必须与setter的参数类型一致。另外,对多个属性的setter都用同一

个名字是违反JavaBean规范的。 (译注:也许是: Class1 getClass() 与 Class2 getClass() 这样是不允许的,尽管它们在语法上是正确


# It is not required that you provide a getter and a setter for every property. In the example above, the fullName property

is read-only, because there is no setter method. It is also possible, but less common, to provide write-only properties.



# It is also possible to create a JavaBean where the getter and setter methods do not match the naming pattern described

above. The standard JavaBeans support classes in the Java language, as well as all classes in the BeanUtils package, allow

you to describe the actual property method names in a BeanInfo class associated with your bean class. See the JavaBeans

Specification for full details.



# The JavaBeans Specification also describes many additional design patterns for event listeners, wiring JavaBeans together

into component hierarchies, and other useful features that are beyond the scope of the BeanUtils package.


Using standard Java coding techniques, it is very easy to deal with JavaBeans if you know ahead of time which bean classes

you will be using, and which properties you are interested in:

Employee employee = ...;
System.out.println("Hello " + employee.getFirstName() + "!")


1.2 External Dependencies 外部的依赖工具。

The commons-beanutils package requires that the following additional packages be available in the application's class path

at runtime:

* Collections Package (Apache Commons), version 1.0 or later
* Logging Package (Apache Commons), version 1.0 or later

2 Standard JavaBeans 标准JavaBean
2.1 Background 背景

As described above, the standard facilities of the Java programming language make it easy and natural to access the property

values of your beans using calls to the appropriate getter methods. But what happens in more sophisticated environments

where you do not necessarily know ahead of time which bean class you are going to be using, or which property you want to

retrieve or modify? The Java language provides classes like java.beans.Introspector, which can examine a Java class at

runtime and identify for you the names of the property getter and setter methods, plus the Reflection capabilities to

dynamically call such a method. However, these APIs can be difficult to use, and expose the application developer to many

unnecessary details of the underlying structure of Java classes. 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




以在运行时检查java类,并且识别属性的getter/setter方法;以及对动态调用这些方法的反射能力(Reflection capabilities)。然而这些

API 很难使用,而且需要把应用程序暴露给Java类的很多不必要的底层结构。BeanUtils包中的API就是为了简化动态的取得/设置bean属性的

,这里的类——以及你关心的属性名——的动态调用 是在应用程序的运行时刻决定的, 而不是在编写,编译应用程序时。

This is the set of needs that are satisfied by the static methods of the PropertyUtils class, which are described further in

this section. First, however, some further definitions will prove to be useful:



The general set of possible property types supported by a JavaBean can be broken into three categories -- some of which are

supported by the standard JavaBeans specification, and some of which are uniquely supported by the BeanUtils package:

一般来说,一个JavaBean的属性分三种-- 某些被标准的JavaBean规范支持,某些只是被BeanUtils包支持。

* Simple - Simple, or scalar, properties have a single value that may be retrieved or modified. The underlying property

type might be a Java language primitive (such as int, a simple object (such as a java.lang.String), or a more complex object

whose class is defined either by the Java language, by the application, or by a class library included with the application.
简单的 - 简单,或者纯的(?),属性只有一个值,可以被查询或修改。基本的属性可以是java语言的原始类型(例如int , 简单的对象


* Indexed - An indexed property stores an ordered collection of objects (all of the same type) that can be individually

accessed by an integer-valued, non-negative index (or subscript). Alternatively, the entire set of values may be set or

retrieved using an array. As an extension to the JavaBeans specification, the BeanUtils package considers any property whose

underlying data type is java.util.List (or an implementation of List) to be indexed as well.
索引化的 - 一个索引化的属性保存了有先后顺序的对象(它们属于同一类型)的集合,这些对象可以通过一个非负整数的索引或脚注所

访问。整个集合可以使用一个数组进行设置或查询。 作为JavaBeans规范的一个扩展, BeanUtils包 认为所有类型为java.util.List(或者


* Mapped - As an extension to standard JavaBeans APIs, the BeanUtils package considers any property whose underlying

value is a java.util.Map to be "mapped". You can set and retrieve individual values via a String-valued key.
映射的 - 作为标准JavaBean API的一个扩展, BeanUtils包认为所有类型为 java.util.Map 的属性,都是被映射的。我们可以通过不同

的字符形式的key 来设置或查询不同的值。

A variety of API methods are provided in the PropertyUtils class to get and set property values of all of these types. In

the code fragments below, assume that there are two bean classes defined with the following method signatures:
PropertyUtils包提供了多种API方法来为所有的类型设置或取得值。在下面的代码片段中,假设有2个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);

2.2 Basic Property Access

Getting and setting simple property values is, well, simple :-). Check out the following API signatures in the Javadocs:
取得或设置简单的属性是,恩,非常简单的:-)。 请看一下 Javadoc中下面的API:

* PropertyUtils.getSimpleProperty(Object bean, String name)
* PropertyUtils.setSimpleProperty(Object bean, String name, Object value)

Using these methods, you might dynamically manipulate the employee's name in an application:

Employee employee = ...;
String firstName = (String)
PropertyUtils.getSimpleProperty(employee, "firstName");
String lastName = (String)
PropertyUtils.getSimpleProperty(employee, "lastName");
... manipulate the values ...
PropertyUtils.setSimpleProperty(employee, "firstName", firstName);
PropertyUtils.setSimpleProperty(employee, "lastName", lastName);

For indexed properties, you have two choices - you can either build a subscript into the "property name" string, using

square brackets, or you can specify the subscript in a separate argument to the method call:
对于索引化的属性,我们有两个选择:或者建立一个属性名[] 数组, 或者在不同的语句中指定数组下标:

* PropertyUtils.getIndexedProperty(Object bean, String name)
* PropertyUtils.getIndexedProperty(Object bean, String name, int index)
* PropertyUtils.setIndexedProperty(Object bean, String name, Object value)
* PropertyUtils.setIndexedProperty(Object bean, String name, int index, Object value)

Only integer constants are allowed when you add a subscript to the property name. If you need to calculate the index of the

entry you wish to retrieve, you can use String concatenation to assemble the property name expression. For example, you

might do either of the following:


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);

In a similar manner, there are two possible method signatures for getting and setting mapped properties. The difference is

that the extra argument is surrounded by parentheses ("(" and ")") instead of square brackets, and it is considered to be a

String-value key used to get or set the appropriate value from an underlying map.


* PropertyUtils.getMappedProperty(Object bean, String name)
* PropertyUtils.getMappedProperty(Object bean, String name, String key)
* PropertyUtils.setMappedProperty(Object bean, String name, Object value)
* PropertyUtils.setMappedProperty(Object bean, String name, String key, Object value)

You can, for example, set the employee's home address in either of these two manners:

例如,你可以使用两种方式设置employee的 home.

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

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

2.3 Nested Property Access 嵌套的属性访问

In all of the examples above, we have assumed that you wished to retrieve the value of a property of the bean being passed

as the first argument to a PropertyUtils method. However, what if the property value you retrieve is really a Java object,

and you wish to retrieve a property of that object instead?



For example, assume we really wanted the city property of the employee's home address. Using standard Java programming

techniques for direct access to the bean properties, we might write:
例如,假设我们实际想要的属性是 employee的 home address 中的city属性。使用标准Java程序的技术来直接访问属性,我们也许这样写:

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

The equivalent mechanism using the PropertyUtils class is called nested property access. To use this approach, you

concatenate together the property names of the access path, using "." separators -- very similar to the way you can perform

nested property access in JavaScript.
使用PropertyUtils实现的等价程序可以叫做 嵌套属性访问。想使用这个方法,需要使用"."来联合各种属性的名字——非常类似于我们在


* PropertyUtils.getNestedProperty(Object bean, String name)
* PropertyUtils.setNestedProperty(Object bean, String name, Object value)

The PropertyUtils equivalent to the above Java expression would be:

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

Finally, for convenience, PropertyUtils provides method signatures that accept any arbitrary combination of simple, indexed,

and mapped property access, using any arbitrary level of nesting:
最后,为了提供方便, PropertyUtils提供了这样的方法:接受各种简单的,索引化的,影射的类型组合的访问,使用任何级别的嵌套:

* PropertyUtils.getProperty(Object bean, String name)
* PropertyUtils.setProperty(Object bean, String name, Object value)

which you might use like this:

Employee employee = ...;
String city = (String) PropertyUtils.getProperty(employee,