内省主要对于JavaBean进行操作,JavaBean是一种特殊的Java类,类内方法符合某种特殊的约定规则。
一个类中的某些方法以set或者get打头,那么这个类就可以称之为JavaBean。它的属性是按照这个类中的set或者get打头的方法来确定的。JavaBean是一种特殊的Java类,主要用于传递数据信息,这种Java类中的方法主要用于访问私有的字段,且方法名符合某种命名规范。
若果要在两个模块之间传递多个消息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象。这些信息在类中用私有字段来存储,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问。JavaBean的属性是根据其中的setter和getter来确定,而不是根据其中的成员变量。
package com.amorvos.Bean.Persion;
public class Persion {
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Persion(int age, int gender, String name) {
super();
this.age = age;
this.gender = gender;
this.name = name;
}
public int getGender() {
return gender;
}
public void setGender(int gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Persion [age=" + age + ", gender=" + gender + ", name=" + name
+ "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private int age;
private int gender;
private String name;
}
正如以上代码,JavaBean中属性是按照这个类中的set或者get打头的方法来确定的。
需要注意的是在JavaBean命名时如果第二个字母是小写的,则把第一个字母变成小写的 Age-->age;如果第二个字母是大写的,那么第一个字母就保持原样大写 CPU-->CPU。
一个符合JavaBean特点的类可以当做普通类一样进行使用,在Java EE开发中,经常要使用JavaBean,很多环境本身就是按照JavaBean方式进行操作。
一、JavaBean的简单内省操作
简单的内省操作可以方便对JavaBean实例的属性设置与获取,示例代码如下:
package com.amorvos.IntroSpector;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import com.amorvos.Bean.Persion;
public class IntroSpectorDemo {
public static void main(String[] args) throws Exception {
Persion p = new Persion(20, 1, "张三");
String propertyName = "age";
PropertyDescriptor pd = getProperty(p, propertyName);
Object value = 10;
setProperty(p, pd, value);
}
private static void setProperty(Persion p, PropertyDescriptor pd,
Object value) throws IllegalAccessException,
InvocationTargetException {
// 获取属性的写方法
Method methodSetAge = pd.getWriteMethod();
methodSetAge.invoke(p, value);
System.out.println(p.getAge());
}
private static PropertyDescriptor getProperty(Persion p, String propertyName)
throws IntrospectionException, IllegalAccessException,
InvocationTargetException {
PropertyDescriptor pd = new PropertyDescriptor(propertyName,
p.getClass());
// 获取属性的读方法
Method methodGetAge = pd.getReadMethod();
Object retval = methodGetAge.invoke(p, null);
System.out.println(retval);
return pd;
}
}
二、JavaBean的复杂内省操作
package com.amorvos.IntroSpector;
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;
import com.amorvos.Bean.Persion;
public class IntroSpectorComplexDemo {
public static void main(String[] args) throws Exception {
Persion p = new Persion(20, 1, "张三");
String propertyName = "age";
Object pd = getProperty(p, propertyName);
Object value = 10;
setProperty(p, propertyName, value);
}
private static void setProperty(Persion p, String propertyName, Object value)
throws IllegalAccessException, InvocationTargetException,
IntrospectionException {
PropertyDescriptor pd = new PropertyDescriptor(propertyName,
p.getClass());
// 获取属性的写方法
Method methodSetAge = pd.getWriteMethod();
methodSetAge.invoke(p, value);
System.out.println(p.getAge());
}
private static Object getProperty(Persion p, String propertyName)
throws IntrospectionException, RuntimeException,
IllegalAccessException, InvocationTargetException {
BeanInfo bInfo = Introspector.getBeanInfo(p.getClass());
PropertyDescriptor[] pds = bInfo.getPropertyDescriptors();
Object retval = null;
for (PropertyDescriptor pd : pds) {
if (pd.getName().equals(propertyName)) {
Method method = pd.getReadMethod();
retval = method.invoke(p, null);
break;
}
}
return retval;
}
}
三、BeanUtils工具包操作JavaBean
BeanUtils处理属性的时候是以字符串的方式来处理的。比如属性本身是int类型的,那么他处理这个属性的时候就会把int类型的数据包装称字符串,然后进行设值或者取值(取出来的值也是一个字符串),BeanUtils自动完成类型的转换。
BeanUtils支持属性的级联操作,也就是说可以直接操作属性的属性。
package com.amorvos.IntroSpector;
import org.apache.commons.beanutils.BeanUtils;
import com.amorvos.Bean.Persion;
public class BeanUtilsDemo {
public static void main(String[] args) throws Exception {
Persion p = new Persion(20, 1, "张三");
String propertyName = "age";
//BeanUtil属性的获取与设置
System.out.println(BeanUtils.getProperty(p, propertyName));
BeanUtils.setProperty(p, propertyName, "8");
System.out.println(p.getAge());
}
}
BeanUtils可以和Map集合进行相互转换,将属性信息通过键值对的形式作为Map集合存储,也可以将Map集合转换为JavaBean中的属性信息的方法。
package com.amorvos.IntroSpector;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.beanutils.BeanUtils;
import com.amorvos.Bean.Persion;
public class BeanUtilsDemo {
public static void main(String[] args) throws Exception {
Persion p = new Persion(20, 1, "张三");
//获取属性封装到Map中
Map properties = BeanUtils.describe(p);
Set ps = properties.entrySet();
Iterator iterator = ps.iterator();
while (iterator.hasNext()) {
Map.Entry me = (Entry) iterator.next();
String name = (String) me.getKey();
String value = (String) me.getValue();
System.out.println(name + "-----" + value);
}
}
}
四、PropertyUtils的使用
PropertyUtils处理属性的时候不需要进行类型的转换,直接以数据本身的数据类型操作
package com.amorvos.IntroSpector;
import org.apache.commons.beanutils.PropertyUtils;
import com.amorvos.Bean.Persion;
public class PropertyUtilsDemo {
public static void main(String[] args) throws Exception {
Persion p = new Persion(20, 1, "张三");
String propertyName = "age";
PropertyUtils.setProperty(p, propertyName, 9);
System.out.println(PropertyUtils.getProperty(p,propertyName).getClass().getName());
}
}