內省是 Java 語言對 Bean 類屬性、事件的一種處理方法(也就是說給定一個javabean對象,我們就可以得到/調用它的所有的get/set方法).
例如類 A 中有屬性 name, 那我們可以通過 getName,setName 來得到其值或者設置新的值.通過 getName/setName 來訪問 name 屬性,這就是默認的規則.
Java 中提供了一套 API 用來訪問某個屬性的 getter/setter 方法,通過這些 API 可以使你不需要了解這個規則,這些 API 存放於包 java.beans 中.
一般的做法是通過類 Introspector 的 getBeanInfo方法 來獲取某個對象的 BeanInfo 信息,然後通過 BeanInfo 來獲取屬性的描述器(PropertyDescriptor),通過這個屬性描述器就可以獲取某個屬性對應的 getter/setter 方法,然後我們就可以通過反射機制來調用這些方法.
內省測試類:Introspector.java
Java代碼
package com.royzhou.bean;
import java.beans.BeanInfo; import java.beans.Introspector; import java.beans.MethodDescriptor; import java.beans.PropertyDescriptor;
public class IntrospectorTest {
public static void main(String[] args) throws Exception {
SimpleBean sb = new SimpleBean("royzhou",new String[]{"football","backetball"});
System.out.println(sb);
/**
* 使用Introspector.getBeanInfo(SimpleBean.class)將Bean的屬性放入到BeanInfo中.
* 第二個參數為截止參數,表示截止到此類之前,不包括此類.
* 如果不設置的話,那麼將會得到本類以及其所有父類的info.
* BeanInfo中包含了SimpleBean的信息
*/
BeanInfo beanInfo = Introspector.getBeanInfo(sb.getClass());
//將每個屬性的信息封裝到一個PropertyDescriptor形成一個數組其中包括屬性名字,讀寫方法,屬性的類型等等PropertyDescriptor[] propertys = beanInfo.getPropertyDescriptors();
for(PropertyDescriptor property : propertys) {
System.out.println("屬性名:" property.getName()); System.out.println("類型:" property.getPropertyType());
}
System.out.println();
System.out.println("列出SimpleBean的所有方法"); MethodDescriptor[] methods = beanInfo.getMethodDescriptors();
for(MethodDescriptor method : methods) {
System.out.println(method.getName());
}
System.out.println();
/**
*重新設置屬性值
*/
for(PropertyDescriptor property : propertys) {
if(property.getPropertyType().isArray()){ //getPropertyType得到屬性類型.
if(property.getPropertyType().isArray()) { if("hobby".equals(property.getName())) {
//getComponentType()可以得到數組類型的元素類型
if(property.getPropertyType().getComponentType().equals(String.class)) {
//getWriteMethod()得到此屬性的set方法----Method對象,然後用invoke調用這個方法
property.getWriteMethod().invoke(sb, new Object[]{new String[]{"tennis","fishing"}});
}
}
}
} else if("name".equals(property.getName())) { property.getWriteMethod().invoke(sb, new Object[] { "royzhou1985" });
}
}
/**
*獲取對象的屬性值
*/
System.out.println("獲取對象的屬性值");
for(PropertyDescriptor property : propertys) {
if(property.getPropertyType().isArray()){ //getPropertyType得到屬性類型.
//getReadMethod()得到此屬性的get方法----Method對象,然後用invoke調用這個方法String[] result=(String[]) property.getReadMethod().invoke(sb, new Object[]{}); System.out.print(property.getName() ":");//getName得到屬性名字for (int j = 0; j < result.length; j ) { System.out.print(result[j] ",");
}
System.out.println();
}
else{
System.out.println(property.getName() ":" property.getReadMethod().invoke(sb, new Object[]{}));
}
}
}
}
package com.royzhou.bean;
import java.beans.BeanInfo; import java.beans.Introspector; import java.beans.MethodDescriptor; import java.beans.PropertyDescriptor;
public class IntrospectorTest {
public static void main(String[] args) throws Exception {
SimpleBean sb = new SimpleBean("royzhou",new String[]{"football","backetball"});
System.out.println(sb);
/**
* 使用Introspector.getBeanInfo(SimpleBean.class)將Bean的屬性放入到BeanInfo中.
* 第二個參數為截止參數,表示截止到此類之前,不包括此類.
* 如果不設置的話,那麼將會得到本類以及其所有父類的info.
* BeanInfo中包含了SimpleBean的信息
*/
BeanInfo beanInfo = Introspector.getBeanInfo(sb.getClass());
//將每個屬性的信息封裝到一個PropertyDescriptor形成一個數組其中包括屬性名字,讀寫方法,屬性的類型等等PropertyDescriptor[] propertys = beanInfo.getPropertyDescriptors();
for(PropertyDescriptor property : propertys) {
System.out.println("屬性名:" property.getName()); System.out.println("類型:" property.getPropertyType());
}
System.out.println();
System.out.println("列出SimpleBean的所有方法"); MethodDescriptor[] methods = beanInfo.getMethodDescriptors();
for(MethodDescriptor method : methods) {
System.out.println(method.getName());
}
System.out.println();
/**
*重新設置屬性值
*/
for(PropertyDescriptor property : propertys) {
if(property.getPropertyType().isArray()){ //getPropertyType得到屬性類型.
if(property.getPropertyType().isArray()) { if("hobby".equals(property.getName())) {
//getComponentType()可以得到數組類型的元素類型
if(property.getPropertyType().getComponentType().equals(String.class)) { //getWriteMethod()得到此屬性的set方法----Method對象,然後用invoke調用這個方法property.getWriteMethod().invoke(sb, new Object[]{new String[]{"tennis","fishing"}});
}
}
}
} else if("name".equals(property.getName())) { property.getWriteMethod().invoke(sb, new Object[] { "royzhou1985" });
}
}
/**
*獲取對象的屬性值
*/
System.out.println("獲取對象的屬性值");
for(PropertyDescriptor property : propertys) {
if(property.getPropertyType().isArray()){ //getPropertyType得到屬性類型.
//getReadMethod()得到此屬性的get方法----Method對象,然後用invoke調用這個方法String[] result=(String[]) property.getReadMethod().invoke(sb, new Object[]{}); System.out.print(property.getName() ":");//getName得到屬性名字for (int j = 0; j < result.length; j ) { System.out.print(result[j] ",");
}
System.out.println();
}
else{
System.out.println(property.getName() ":" property.getReadMethod().invoke(sb, new Object[]{}));
}
}
}
}
輸出結果:
com.royzhou.bean.SimpleBean@757aef
name:=royzhou
hobby:football,backetball,
屬性名:class
類型:class java.lang.Class
屬性名:hobby
類型:class [Ljava.lang.String;
屬性名:name
類型:class java.lang.String
列出SimpleBean的所有方法
hashCode
setHobby
equals
wait
wait
notify
getClass
toString
notifyAll
getHobby
setName
wait
getName
獲取對象的屬性值
class:class com.royzhou.bean.SimpleBean hobby:tennis,fishing,
name:royzhou1985
[火星人 ] java內省機制已經有790次圍觀