Back

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

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

commons-beanutils
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.

JavaBean这个名词,是从JAVA语言的一个组件体系的API而来。以符合JavaBean设计模式而写出的java类,更容易使java开发人员理解该类的

功能,也可以让javaBeans-aware工具使用自省这个特性得知该类的属性和方法,并把它们在开发工具中已可视的,漂亮的形式表现出来。

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:
class必须是public,提供一个无参数的构造函数。这就允许工具程序和应用程序能动态的建立该class的新实例,而不必提前知道这个class

的名字。例如:

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.

某个类具有无参构造函数的必然结果,就是对不同的实例的配置都是分别不同的。这样做的代表性的例子就是定义一组你的class的属性集合

,这些属性可以改变类的行为或者保存数据。属性的命名规范是:小写开头,字母是合法的。

# 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规范定

义了它们的命名规范(原文:定义了命名的设计模式),把get或set作为方法名的前缀,后接该属性,该属性的第一个字母大写。所以,你的

某个代表了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.

可以从上面的例子看到,有一个涉及到布尔变量的属性,——如果有更利于理解的话,你有可以把它的getter方法以"get"前缀命名。

# 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.

并不是每个属性都需要getter/setter方法。上面的例子中,属性fullName就是只读的,因为它没有setter方法。比较少见但也有可能的情况

是,属性是只写的。(译注:即没有getter方法)

# 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.

也可以建立一个getter/setter方法不符合上面说到的命名规范的JavaBean。BeanUtils包里就是这样做的,它允许你在一个BeanInfo类中描述

实际的属性名,然后把这个类与你的bean相关联。详细情况请看JavaBeans规范。

# 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.

JavaBean规范也描述了其他的设计模式,比如对事件监听器的,对把多个JavaBean组织到一起的,以及超越了BeanUtils包范围的特性。


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() + "!")

在预先知道类名以及属性名的情况下,使用标准的Java编码技术,让人很容易的处理JavaBean。

1.2 External Dependencies 外部的依赖工具。

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

at runtime:
commons-beanutils包在运行时需要在应用的路径存在下面的包:


* 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

classes.

如上所述,Java程序语言的标准程序,通过调用对应的getter方法来取得某个属性的值变的容易和自然。但是在更加复杂的环境中,如果不事

先知道用到的某个类的名字,或者用于查询,修改的某个属性名的话,将会发生什么?Java语言提供了java.beans.Introspector,这个类可

以在运行时检查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:

这些需求就是已经被PropertyUtils类的静态方法所满足的,将在本节的后面进行详述。首先,恩,一些提前的定义是比较有用的:(这个

however应该如何翻译……?)


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 , 简单的对象

(如java.lang.String))或者更加复杂的对象,被java语言,或者应用,或者应用中包含的类库。

* 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(或者

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 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.
类似的方式,映射属性的getter/setter有两个可能的方法。区别是多余的参数被圆括号而不是放括号。而且它是被用来作为字符串值的KEY来

取得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?

在上面的例子中,我们假设通过第一参数查询某个属性的值。可是,如果查询的属性本身就是个java对象,而我们却希望只查询这个对象的某

个属性,该怎么做?


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实现的等价程序可以叫做 嵌套属性访问。想使用这个方法,需要使用"."来联合各种属性的名字——非常类似于我们在

Javascript中的属性访问。

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

The PropertyUtils equivalent to the above Java expression would be:
使用PropertyUtils实现程序应该是:

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,
"subordinate[3].address(home).city");

Back