java基礎加強_JavaBean內省


JavaBean內省概述:
JavaBean是一種特殊的Java類,主要用於傳遞數據信息,這種java類中的方法主要用於訪問私有的字段,且方法名符合某種命名規則。

什麼時候使用JavaBean:
如果要在兩個模塊之間傳遞多個信息,可以將這些信息封裝到一個JavaBean中,這種JavaBean的實例對象通常稱之爲值對象(Value Object,簡稱VO)。這些信息在類中用私有字段來存儲,如果讀取或設置這些字段的值,則需要通過一些相應的方法來訪問。

JavaBean中的字段命名規則:
這些方法的名稱叫什麼好呢?JavaBean的屬性是根據其中的setter和getter方法來確定的,而不是根據其中的成員變量。如果方法名爲setId,中文意思即爲設置id,至於你把它存到哪個變量上,用管嗎?如果方法名爲getId,中文意思即爲獲取id,至於你從哪個變量上取,用管嗎?去掉set前綴,剩餘部分就是屬性名,如果剩餘部分的第二個字母是小寫的,則把剩餘部分的首字母改成小的。
setId()的屬性名id
isLast()的屬性名last
setCPU的屬性名是什麼?CPU
getUPS的屬性名是什麼?UPS
總之,一個類被當作javaBean使用時,JavaBean的屬性是根據方法名推斷出來的,它根本看不到java類內部的成員變量。
一個符合JavaBean特點的類可以當作普通類一樣進行使用,但把它當JavaBean用肯定需要帶來一些額外的好處,我們纔會去了解和應用JavaBean!

使用JavaBean的好處:
在Java EE開發中,經常要使用到JavaBean。很多環境就要求按JavaBean方式進行操作,別人都這麼用和要求這麼做,那你就沒什麼挑選的餘地!
JDK中提供了對JavaBean進行操作的一些API,這套API就稱爲內省。如果要你自己去通過getX方法來訪問私有的x,怎麼做,有一定難度吧?用內省這套api操作JavaBean比用普通類的方式更方便。

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工具包
導入步驟:
方法一:右鍵工程文件-->Build Path-->Add to Build Path即可
這種方法只是指定了工具包路徑
方法二:在工程文件目錄下,創建一個lib文件夾,將兩個工具包導入lib文件夾中,然後右鍵工具包-->Build Path-->Add to Build Path
這種方法不但添加了BuildPath,還將工具包也導入了工程文件夾根目錄下,在拷貝工程文件時,工具包也會被一同拷貝走

使用BeanUtils類改寫上面的代碼示例:
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類中的方法,傳入的參數類型只能是屬性本身的類型

發佈了57 篇原創文章 · 獲贊 4 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章