java bean的反射类_JAVA中反射机制五(JavaBean的内省与BeanUtils库)
內(nèi)省(Introspector) 是Java?語言對(duì)JavaBean類屬性、事件的一種缺省處理方法。
JavaBean是一種特殊的類,主要用于傳遞數(shù)據(jù)信息,這種類中的方法主要用于訪問私有的字段,且方法名符合某種命名規(guī)則。如果在兩個(gè)模塊之間傳遞信息,可以將信息封裝進(jìn)JavaBean中,這種對(duì)象稱為“值對(duì)象”(Value Object),或“VO”。方法比較少。這些信息儲(chǔ)存在類的私有變量中,通過set()、get()獲得。
例如類UserInfo :
package com.peidasoft.instrospector;
public class UserInfo {
private long userId;
private String userName;
private int age;
private String emailAddress;
public long getUserId() {
return userId;
}
public void setUserId(long userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
}
在類UserInfo中有屬性u(píng)serName,那我們可以通過getUserName,?setUserName來得到其值或者設(shè)置新的值。通過getUserName/setUserName來訪問userName屬性,這就是默認(rèn)的規(guī)則。Java?JDK中提供了一套API用來訪問某個(gè)屬性的getter/setter方法,這就是內(nèi)省。
JDK內(nèi)省類庫:
PropertyDescriptor類:(屬性描述器)
PropertyDescriptor類表示JavaBean類通過存儲(chǔ)器導(dǎo)出一個(gè)屬性。主要方法:
1. getPropertyType(),獲得屬性的Class對(duì)象;
2. getReadMethod(),獲得用于讀取屬性值的方法;
3. getWriteMethod(),獲得用于寫入屬性值的方法;
4. hashCode(),獲取對(duì)象的哈希值;
5. setReadMethod(Method readMethod),設(shè)置用于讀取屬性值的方法;
6. setWriteMethod(Method writeMethod),設(shè)置用于寫入屬性值的方法。
實(shí)例代碼如下:
package com.peidasoft.instrospector;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
public class BeanInfoUtil {
// 設(shè)置bean的某個(gè)屬性值
public static void setProperty(UserInfo userInfo, String userName) throws Exception {
// 獲取bean的某個(gè)屬性的描述符
PropertyDescriptor propDesc = new PropertyDescriptor(userName, UserInfo.class);
// 獲得用于寫入屬性值的方法
Method methodSetUserName = propDesc.getWriteMethod();
// 寫入屬性值
methodSetUserName.invoke(userInfo, "wong");
System.out.println("set userName:" + userInfo.getUserName());
}
// 獲取bean的某個(gè)屬性值
public static void getProperty(UserInfo userInfo, String userName) throws Exception {
// 獲取Bean的某個(gè)屬性的描述符
PropertyDescriptor proDescriptor = new PropertyDescriptor(userName, UserInfo.class);
// 獲得用于讀取屬性值的方法
Method methodGetUserName = proDescriptor.getReadMethod();
// 讀取屬性值
Object objUserName = methodGetUserName.invoke(userInfo);
System.out.println("get userName:" + objUserName.toString());
}
}
Introspector類:
將JavaBean中的屬性封裝起來進(jìn)行操作。在程序把一個(gè)類當(dāng)做JavaBean來看,就是調(diào)用Introspector.getBeanInfo()方法,得到的BeanInfo對(duì)象封裝了把這個(gè)類當(dāng)做JavaBean看的結(jié)果信息,即屬性的信息。
getPropertyDescriptors(),獲得屬性的描述,可以采用遍歷BeanInfo的方法,來查找、設(shè)置類的屬性。具體代碼如下:
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
public class BeanInfoUtil {
// 通過內(nèi)省設(shè)置bean的某個(gè)屬性值
public static void setPropertyByIntrospector(UserInfo userInfo, String userName) throws Exception {
// 獲取bean信息
BeanInfo beanInfo = Introspector.getBeanInfo(UserInfo.class);
// 獲取bean的所有屬性列表
PropertyDescriptor[] proDescrtptors = beanInfo.getPropertyDescriptors();
// 遍歷屬性列表,查找指定的屬性
if (proDescrtptors != null && proDescrtptors.length > 0) {
for (PropertyDescriptor propDesc : proDescrtptors) {
// 找到則寫入屬性值
if (propDesc.getName().equals(userName)) {
Method methodSetUserName = propDesc.getWriteMethod();
methodSetUserName.invoke(userInfo, "alan"); // 寫入屬性值
System.out.println("set userName:" + userInfo.getUserName());
break;
}
}
}
}
// 通過內(nèi)省獲取bean的某個(gè)屬性值
public static void getPropertyByIntrospector(UserInfo userInfo, String userName) throws Exception {
BeanInfo beanInfo = Introspector.getBeanInfo(UserInfo.class);
PropertyDescriptor[] proDescrtptors = beanInfo.getPropertyDescriptors();
if (proDescrtptors != null && proDescrtptors.length > 0) {
for (PropertyDescriptor propDesc : proDescrtptors) {
if (propDesc.getName().equals(userName)) {
Method methodGetUserName = propDesc.getReadMethod();
Object objUserName = methodGetUserName.invoke(userInfo);
System.out.println("get userName:" + objUserName.toString());
break;
}
}
}
}
}
通過這兩個(gè)類的比較可以看出,都是需要獲得PropertyDescriptor,只是方式不一樣:前者通過創(chuàng)建對(duì)象直接獲得,后者需要遍歷,所以使用PropertyDescriptor類更加方便。
package com.peidasoft.instrospector;
public class BeanInfoTest {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
UserInfo userInfo = new UserInfo();
userInfo.setUserName("peida");
try {
BeanInfoUtil.getProperty(userInfo, "userName");
BeanInfoUtil.setProperty(userInfo, "userName");
BeanInfoUtil.getProperty(userInfo, "userName");
BeanInfoUtil.setPropertyByIntrospector(userInfo, "userName");
BeanInfoUtil.getPropertyByIntrospector(userInfo, "userName");
BeanInfoUtil.setProperty(userInfo, "age"); // IllegalArgumentException
} catch (Exception e) {
e.printStackTrace();
}
}
}
輸出結(jié)果:
get userName:peida
set userName:wong
get userName:wong
set userName:alan
get userName:alan
java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.peidasoft.instrospector.BeanInfoUtil.setProperty(BeanInfoUtil.java:22)
at com.peidasoft.instrospector.BeanInfoTest.main(BeanInfoTest.java:26)
說明:BeanInfoUtil.setProperty(userInfo,"age");報(bào)錯(cuò)是應(yīng)為age屬性是int數(shù)據(jù)類型,而setProperty方法里面默認(rèn)給age屬性賦的值是String類型。所以會(huì)爆出argument type mismatch參數(shù)類型不匹配的錯(cuò)誤信息。
BeanUtils工具包:
由上述可看出,內(nèi)省操作非常的繁瑣,所以所以Apache開發(fā)了一套簡(jiǎn)單、易用的API來操作Bean的屬性——BeanUtils工具包。
BeanUtils工具包:下載:http://commons.apache.org/beanutils/,注意:應(yīng)用的時(shí)候還需要一個(gè)logging包http://commons.apache.org/logging/
使用BeanUtils工具包完成上面的測(cè)試代碼:
package com.peidasoft.instrospector;
import java.lang.reflect.InvocationTargetException;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
public class BeanInfoTest {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
UserInfo userInfo = new UserInfo();
userInfo.setUserName("peida");
try {
BeanUtils.setProperty(userInfo, "userName", "peida");
System.out.println("set userName:" + userInfo.getUserName());
System.out.println("get userName:" + BeanUtils.getProperty(userInfo, "userName"));
BeanUtils.setProperty(userInfo, "age", 18);
System.out.println("set age:" + userInfo.getAge());
System.out.println("get age:" + BeanUtils.getProperty(userInfo, "age"));
System.out.println("get userName type:" + BeanUtils.getProperty(userInfo, "userName").getClass().getName());
System.out.println("get age type:" + BeanUtils.getProperty(userInfo, "age").getClass().getName());
PropertyUtils.setProperty(userInfo, "age", 8);
System.out.println(PropertyUtils.getProperty(userInfo, "age"));
System.out.println(PropertyUtils.getProperty(userInfo, "age").getClass().getName());
PropertyUtils.setProperty(userInfo, "age", "8"); // IllegalArgumentException
} catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
運(yùn)行結(jié)果:
[java] view plain copy
set userName:peida
get userName:peida
set age:18
get age:18
get userName type:java.lang.String
get age type:java.lang.String
8
java.lang.Integer
Exception in thread "main" java.lang.IllegalArgumentException: Cannot invoke com.peidasoft.instrospector.UserInfo.setAge on bean class
'class com.peidasoft.instrospector.UserInfo' - argument type mismatch - had objects of type "java.lang.String" but expected signature "int"
at org.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(PropertyUtilsBean.java:2181)
at org.apache.commons.beanutils.PropertyUtilsBean.setSimpleProperty(PropertyUtilsBean.java:2097)
at org.apache.commons.beanutils.PropertyUtilsBean.setNestedProperty(PropertyUtilsBean.java:1903)
at org.apache.commons.beanutils.PropertyUtilsBean.setProperty(PropertyUtilsBean.java:2010)
at org.apache.commons.beanutils.PropertyUtils.setProperty(PropertyUtils.java:896)
at com.peidasoft.instrospector.BeanInfoTest.main(BeanInfoTest.java:32)
Caused by: java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(PropertyUtilsBean.java:2116)
... 5 more
說明:
1. 獲得屬性的值,例如,BeanUtils.getProperty(userInfo, "userName"),返回字符串。
2. 設(shè)置屬性的值,例如,BeanUtils.setProperty(userInfo, "age", 8),參數(shù)是字符串或基本類型自動(dòng)包裝。設(shè)置屬性的值是字符串,獲得的值也是字符串,不是基本類型。 3. BeanUtils的特點(diǎn):
1). 對(duì)基本數(shù)據(jù)類型的屬性的操作:在WEB開發(fā)、使用中,錄入和顯示時(shí),值會(huì)被轉(zhuǎn)換成字符串,但底層運(yùn)算用的是基本類型,這些類型轉(zhuǎn)到動(dòng)作由BeanUtils自動(dòng)完成。
2). 對(duì)引用數(shù)據(jù)類型的屬性的操作:首先在類中必須有對(duì)象,不能是null,例如,private Date birthday=new Date();。操作的是對(duì)象的屬性而不是整個(gè)對(duì)象,例如,BeanUtils.setProperty(userInfo, "birthday.time", 111111);
package com.peidasoft.Introspector;
import java.util.Date;
public class UserInfo {
private Date birthday = new Date(); // 引用類型的屬性,不能為null
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Date getBirthday() {
return birthday;
}
}
package com.peidasoft.Beanutil;
import java.lang.reflect.InvocationTargetException;
import org.apache.commons.beanutils.BeanUtils;
import com.peidasoft.Introspector.UserInfo;
public class BeanUtilTest {
public static void main(String[] args) {
UserInfo userInfo=new UserInfo();
try {
BeanUtils.setProperty(userInfo, "birthday.time","111111"); // 操作對(duì)象的屬性,而不是整個(gè)對(duì)象
Object obj = BeanUtils.getProperty(userInfo, "birthday.time");
System.out.println(obj);
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
catch (InvocationTargetException e) {
e.printStackTrace();
}
catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
3. PropertyUtils類和BeanUtils不同在于,運(yùn)行g(shù)etProperty、setProperty操作時(shí),沒有類型轉(zhuǎn)換,使用屬性的原有類型或者包裝類。由于age屬性的數(shù)據(jù)類型是int,所以方法PropertyUtils.setProperty(userInfo,"age", "8")會(huì)爆出數(shù)據(jù)類型不匹配,無法將值賦給屬性。
聲明本文轉(zhuǎn)自:http://blog.csdn.net/zhoudaxia/article/details/33783321
總結(jié)
以上是生活随笔為你收集整理的java bean的反射类_JAVA中反射机制五(JavaBean的内省与BeanUtils库)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: mysql中set什么意思?(Mysql
 - 下一篇: 2019年清华同方台式机如何