Wiki上的解释:
在计算机科学中,内省是指计算机程序在运行时(Run time)检查对象(Object)类型的一种能力,通常也可以称作运行时类型检查。 不应该将内省和反射混淆。相对于内省,反射更进一步,是指计算机程序在运行时(Run time)可以访问、检测和修改它本身状态或行为的一种能力。
内省和反射有什么区别?
反射是在运行状态把Java类中的各种成分映射成相应的Java类,可以动态的获取所有的属性以及动态调用任意一个方法,强调的是运行状态。
内省(IntroSpector)是Java 语言对 Bean 类属性、事件的一种缺省处理方法。 JavaBean是一种特殊的类,主要用于传递数据信息,这种类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。如果在两个模块之间传递信息,可以将信息封装进JavaBean中,这种对象称为“值对象”(Value Object),或“VO”。方法比较少。这些信息储存在类的私有变量中,通过set()、get()获得。内省机制是通过反射来实现的,BeanInfo用来暴露一个bean的属性、方法和事件,以后我们就可以操纵该JavaBean的属性。
在Java内省中,用到的基本上就是上述几个类。 通过BeanInfo这个类就可以获取到类中的方法和属性。例如类 A 中有属性 name, 那我们可以通过 getName,setName 来得到其值或者设置新的值。通过 getName/setName 来访问 name 属性,这就是默认的规则。 Java 中提供了一套 API 用来访问某个属性的 getter/setter 方法,通过这些 API 可以使你不需要了解这个规则(但你最好还是要搞清楚),这些 API 存放于包 java.beans 中,一般的做法是通过类 Introspector 的 getBeanInfo方法 来获取某个对象的 BeanInfo 信息,然后通过 BeanInfo 来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后我们就可以通过反射机制来调用这些方法,这就是内省机制。
JDK内省类库
java.beans.Introspector:Introspector 类为通过工具学习有关受目标 Java Bean 支持的属性、事件和方法的知识提供了一个标准方法。
java.beans.BeanInfo接口:希望提供有关其 bean 的显式信息的 bean 实现者可以提供某个 BeanInfo 类,该类实现此 BeanInfo 接口并提供有关其 bean 的方法、属性、事件等显式信息。
java.beans.PropertyDescriptor:PropertyDescriptor 描述 Java Bean 通过一对存储器方法导出的一个属性。
内省代码实现
内省机制单元测试代码
package com.study.java.junit;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Date;
import org.junit.Before;
import org.junit.Test;
import com.study.java.domain.User;
/**
* @Name: IntrospectorTest
* @Description: JavaBean-API:内省机制测试类
* @Author: XXX
* @CreateDate: XXX
* @Version: V1.0
*/
public class IntrospectorTest {
private User user ;
@Before
public void init() {
user = new User() ;
user.setName("张三") ;
user.setAge(21) ;
user.setGender(true) ;
user.setBirthday(new Date()) ;
user.setAddress("北京丰台") ;
}
/**
* @Name: getBeanPropertyInfo
* @Description: 获取User-Bean的所有属性信息
* @Author: XXX
* @Version: V1.0
* @CreateDate: XXX
* @Parameters: @throws Exception
* @Return: void
*/
@Test
public void getBeanPropertyInfo() throws Exception {
//获取User-BeanInfo对象:beanInfo是对一个Bean的描述,可以通过它取得Bean内部的信息
/**
* 获取User-BeanInfo对象
* 1、Introspector类
* 是一个工具类,提供了一系列取得BeanInfo的方法;
* 2、BeanInfo接口
* 对一个JavaBean的描述,可以通过它取得Bean内部的信息;
* 3、PropertyDescriptor属性描述器类
* 对一个Bean属性的描述,它提供了一系列对Bean属性进行操作的方法
*/
BeanInfo userBeanInfo = Introspector.getBeanInfo(User.class) ;
PropertyDescriptor[] pds = userBeanInfo.getPropertyDescriptors() ;
for (PropertyDescriptor pd : pds) {
Method method = pd.getReadMethod() ;
String methodName = method.getName() ;
Object result = method.invoke(user) ;
System.out.println(methodName + "-->" + result);
}
}
/**
* @Name: getBeanPropertyByName
* @Description: 获取指定属性名称的属性描述器,并对属性进行操作
* @Author: XXX
* @Version: V1.0
* @CreateDate: XXX
* @Parameters:
* @Return: void
*/
@Test
public void getBeanPropertyByName() throws Exception {
//获取name属性的属性描述器
PropertyDescriptor pd = new PropertyDescriptor("name", user.getClass()) ;
//得到name属性的getter方法
Method readMethod = pd.getReadMethod() ;
//执行getter方法,获取返回值,即name属性的值
String result = (String) readMethod.invoke(user) ;
System.out.println("user.name" + "-->" + result);
//得到name属性的setter方法
Method writeMethod = pd.getWriteMethod() ;
//执行setter方法,修改name属性的值
writeMethod.invoke(user, "李四") ;
System.out.println("user.name" + "-->" + user.getName());
}
}
MyBeanUtils封装工具类
package com.study.java.utils;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Map;
/**
* @Name: MyBeanUtils
* @Description: JavaBean属性操作工具类
* @Author: XXX
* @CreateDate: 2017-3-9 上午10:40:01
* @Version: V1.0
*/
public class MyBeanUtils {
/**
* @Name: getPropertyValue
* @Description: 根据指定的属性名称获取属性值
* @Author: XXX
* @Version: V1.0
* @CreateDate: 2017-3-9 上午10:55:17
* @Parameters: @param propertyName 属性名称
* @Parameters: @param bean bean实例对象
* @Return: Object 返回getter方法的返回值,即属性值
*/
public static Object getPropertyValue(String propertyName, Object bean) {
Object propertyValue = null ;
try {
PropertyDescriptor pd = new PropertyDescriptor(propertyName, bean.getClass()) ;
Method method = pd.getReadMethod() ;
propertyValue = method.invoke(bean) ;
} catch (Exception e) {
e.printStackTrace();
}
return propertyValue ;
}
/**
* @Name: setProperty
* @Description: 设置/修改属性的内容
* @Author: XXX
* @Version: V1.0
* @CreateDate: 2017-3-9 上午11:01:23
* @Parameters: @param bean Bean实例对象
* @Parameters: @param name 属性名
* @Parameters: @param value 修改内容
* @Return: void 无
*/
public static void setProperty(Object bean, String name, Object value) {
try {
PropertyDescriptor pd = new PropertyDescriptor(name, bean.getClass()) ;
Method method = pd.getWriteMethod() ;
method.invoke(bean, value) ;
} catch (Exception e) {
e.printStackTrace() ;
}
}
/**
* @Name: populate
* @Description: 将Map中的内容封装到JavaBean
* 说明:
* Map中的key必须与JavaBean中的属性名称相同
* Map中的value传递给JavaBean对应的属性
* @Author: XXX
* @Version: V1.0
* @CreateDate: XXX
* @Parameters: @param bean
* @Parameters: @param map
* @Return: void
*/
public static Object populate(Object bean, Map<String, Object> map) {
if(map != null && map.size() > 0) {
for(Map.Entry<String, Object> entry : map.entrySet()) {
String propertyName = entry.getKey() ;
Object propertyValue = entry.getValue() ;
try {
PropertyDescriptor pd = new PropertyDescriptor(propertyName, bean.getClass()) ;
Method method = pd.getWriteMethod() ;
method.invoke(bean, propertyValue) ;
} catch (Exception e) {
throw new RuntimeException(e) ;
}
}
}
return bean ;
}
}
工具类单元测试代码
package com.study.java.junit;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import com.study.java.domain.User;
import com.study.java.utils.MyBeanUtils;
/**
* @Name: MyBeanUtilsTest
* @Description: JavaBean属性操作工具测试类
* @Author: XXX
* @CreateDate: XXX
* @Version: V1.0
*/
public class MyBeanUtilsTest {
private User user ;
@Before
public void init() {
user = new User() ;
user.setName("张三") ;
user.setAge(21) ;
user.setGender(true) ;
user.setBirthday(new Date()) ;
user.setAddress("北京丰台") ;
}
@Test
public void testSetPropertyValue() {
System.out.println(user);
//设置String类型数据
MyBeanUtils.setProperty(user, "name", "李思思") ;
//设置int类型数据
MyBeanUtils.setProperty(user, "age", 23) ;
//设置boolean类型数据
MyBeanUtils.setProperty(user, "gender", false) ;
//设置Date类型数据
MyBeanUtils.setProperty(user, "birthday", new Date(13213412412L)) ;
System.out.println(user);
}
@Test
public void testGetPropertyValue() {
//获取String类型属性
String name = (String) MyBeanUtils.getPropertyValue("name", user) ;
//获取int类型属性
int age = (int) MyBeanUtils.getPropertyValue("age", user) ;
//获取boolean类型属性
boolean gender = (boolean) MyBeanUtils.getPropertyValue("gender", user) ;
//获取Date类型属性
Date birthday = (Date) MyBeanUtils.getPropertyValue("birthday", user) ;
System.out.println(name + "," + age + "," + gender + "," + birthday + ".");
}
@Test
public void testPopulate() {
//向Map集合中封装数据,适用于request.getParameterMap() ;
Map<String, Object> map = new HashMap<String, Object>() ;
map.put("name", "王五") ;
map.put("age", 21) ;
map.put("gender", true) ;
map.put("birthday", new Date(32131412L)) ;
String[] hobbies = {"打球", "唱歌"} ;
map.put("hobbies", hobbies) ;
//将Map集合中的数据封装到UserBean
User u = (User) MyBeanUtils.populate(new User(), map) ;
System.out.println(u);
}
}
---------------------
原文:https://blog.csdn.net/u010445297/article/details/60967146