JavaBean是一種特殊的Java類,主要用於傳遞數據信息,這種java類中的方法主要用於訪問私有的字段,且方法名符合某種命名規則。
如果要在兩個模塊之間傳遞多個信息,可以將這些信息封裝到一個JavaBean中,這種JavaBean的實例對象通常稱之爲值對象(Value Object,簡稱VO)。這些信息在類中用私有字段來存儲,如果讀取或設置這些字段的值,則需要通過一些相應的方法來訪問。
這些方法的名稱叫什麼好呢?JavaBean的屬性是根據其中的setter和getter方法來確定的,而不是根據其中的成員變量。如果方法名爲setId,中文意思即爲設置id,至於你把它存到哪個變量上,用管嗎?如果方法名爲getId,中文意思即爲獲取id,至於你從哪個變量上取,用管嗎?去掉set前綴,剩餘部分就是屬性名,如果剩餘部分的第二個字母是小寫的,則把剩餘部分的首字母改成小的。setId()的屬性名idisLast()的屬性名lastsetCPU的屬性名是什麼?CPUgetUPS的屬性名是什麼?UPS總之,一個類被當作javaBean使用時,JavaBean的屬性是根據方法名推斷出來的,它根本看不到java類內部的成員變量。一個符合JavaBean特點的類可以當作普通類一樣進行使用,但把它當JavaBean用肯定需要帶來一些額外的好處,我們纔會去了解和應用JavaBean!
在Java EE開發中,經常要使用到JavaBean。很多環境就要求按JavaBean方式進行操作,別人都這麼用和要求這麼做,那你就沒什麼挑選的餘地!JDK中提供了對JavaBean進行操作的一些API,這套API就稱爲內省。如果要你自己去通過getX方法來訪問私有的x,怎麼做,有一定難度吧?用內省這套api操作JavaBean比用普通類的方式更方便。
package com.learn;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class PropertyTest
{
/**
* @param args
*/
public static void main(String[] args) throws Exception
{
//創建要操作的類的對象
ReflectPoint rp = new ReflectPoint(3, 4);
//定義要獲取的x的值
String propertyName = "x";
//get()方法重構
Object returnValue = getProperty(rp, propertyName);
System.out.println(returnValue);
//set()方法重構
Object value = 7;
setProperty(rp, propertyName, value);
System.out.println(rp.getX());
}
private static void setProperty(ReflectPoint rp, String propertyName,
Object value) throws IntrospectionException,
IllegalAccessException, InvocationTargetException
{
PropertyDescriptor pd1 = new PropertyDescriptor(propertyName,rp.getClass());
//設置rp對象中X的值
Method methodSetX = pd1.getWriteMethod();
methodSetX.invoke(rp, value);
}
private static Object getProperty(ReflectPoint rp,
String propertyName) throws IntrospectionException,
IllegalAccessException, InvocationTargetException
{
//創建PropertyDescriptor對象
PropertyDescriptor pd = new PropertyDescriptor(propertyName,rp.getClass());
//通過pd對象獲取rp對象中的get方法
Method methodGetX = pd.getReadMethod();
//獲取get()方法中x的值
Object returnValue = methodGetX.invoke(rp);
return returnValue;
}
}
方法重構其實就是將方法單獨封裝出去,只要明確了方法類型和參與運算的未知參數即可抽取;得到BeanInfo最好採用“obj.getClass()”方式,而不要採用“類名.class”方式,這樣程序更通用。
代碼示例:採用遍歷BeanInfo的所有屬性方式來查找和設置某個RefectPoint對象的x屬性。在程序中把一個類當作JavaBean來看,就是調用IntroSpector.getBeanInfo方法, 得到的BeanInfo對象封裝了把這個類當作JavaBean看的結果信息。
package com.learn;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class PropertyTest2
{
/**
* @param args
*/
public static void main(String[] args) throws Exception
{
// TODO Auto-generated method stub
ReflectPoint rp = new ReflectPoint(2,3);
String propertyName = "x";
Object returnValue = getProperty(rp, propertyName);
System.out.println(returnValue);
}
private static Object getProperty(ReflectPoint rp, String propertyName)
throws IntrospectionException, IllegalAccessException,
InvocationTargetException
{
//獲取rp所有方法和屬性
BeanInfo beanInfo = Introspector.getBeanInfo(rp.getClass());
//創建pd對象
PropertyDescriptor pd = new PropertyDescriptor(propertyName,rp.getClass());
//取出所有方法和屬性存入集合
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
Object returnValue = null;
//遍歷集合中的屬性
for (PropertyDescriptor p : pds)
{
//判斷是否有屬性名和要查找的字段相同
if(pd.getName().equals(propertyName))
{
//獲取字段所在的方法
Method methodGetX = pd.getReadMethod();
//調用底層方法
returnValue = methodGetX.invoke(rp);
break;
}
}
return returnValue;
}
}
java.beans.PropertyDescriptor
|-- Method getReadMethod()獲得應該用於讀取屬性值的方法。|-- Method getWriteMethod()獲得應該用於寫入屬性值的方法。java.beans.Introspactor
|--static BeanInfo getBeanInfo(Class<?> beanClass)在 Java Bean 上進行內省,瞭解其所有屬性、公開的方法和事件。
|--PropertyDescriptor[] getPropertyDescriptors()獲得 beans PropertyDescriptor。
使用BeanUtils工具包操作JavaBean
使用BeanUtils工具,要先導入BeanUtils工具包和logging工具包package cn.itheima.learn;
import org.apache.commons.beanutils.BeanUtils;
public class PropertyTest3
{
/**
* @param args
*/
public static void main(String[] args) throws Exception
{
//創建要操作的類的對象
ReflectPoint rp = new ReflectPoint(3, 4);
//定義要獲取的x的值
String propertyName = "x";
//使用BeanUtils工具中的getProperty()方法獲取x的值
System.out.println(BeanUtils.getProperty(rp, "x"));
//使用BeanUtils工具中的setProperty()方法設置x的值
BeanUtils.setProperty(rp, propertyName, "9");
System.out.println(rp.getX());
}
}
BeanUtils類中的方法
static voidsetProperty(Object bean, String name, Object value):將某個對象中的某個變量設置爲某個值static StringgetProperty(Object bean, String name):獲取某個對象中的某個變量值這兩個方法中的變量name支持屬性鏈,舉例:private birthday = new Date();Date類中有一個getTime()方法,所以就有一個time屬性我們可以直接設置time屬性birthday.time
BeanUtils工具類在對對象的屬性進行操作的時候,會自動進行類型轉換。但是設置屬性值的時候傳入的參數可以是String類型,也可以是它本身的類型,這是因爲內部發生了自動類型轉換。
PropertyUtils類中同樣有兩個這樣的方法:static voidsetProperty(Object bean, String name, Object value)static ObjectgetProperty(Object bean, String name):與上面的返回值類型不同他們的區別:BeanUtils類中的方法,會自動進行類型轉換,設置屬性值時可以傳入String類型的參數PropertyUtils類中的方法,傳入的參數類型只能是屬性本身的類型