比反射更强大的技术,内省技术
2019-09-07 23:57:41 ZackSock 阅读数 977更多
在学习Java过程中,总是层层递进的。
差不多从数据类型到IO、异常就算基础部分(不同书不一样)。
之后就是Java的进阶,一般我们都会学到泛型、反射之类的。
今天要说的东西,就和反射有关系,叫做“内省技术”。
“内省技术”是基于反射技术的,提供了更多的便于操作JavaBean的API。
一般的话,我们只有学到JavaWeb才会称呼JavaBean,由此可知“内省技术”属于JavaWeb的内容(搞笑逻辑,别介意)。
1、什么是内省
前面已经说了,内省就是JDK提供的JavaBean操作的API,基于反射技术。
2、如何用代码实现内省
内省使用到的类就是Introspector,说到底学习内省就是学习类Introspecteor类的使用。
因为内省技术还是比较简单的,下面就直接用代码举例。先创建一个Person类:
public class Person{
private String name;
private String sex;
/**
* 省略get、set方法
*/
public Person(){
}
}
类准备好了就可以开始使用内省了。
第一步:获取BeanInfo对象
-
@Test
-
public void demo(){
-
//调用Introspector中的getBeanInfo()方法,传入要获取信息的类的Class对象
-
BeanInfo beanInfo = Introspector.getBeanInfo(Person.class);
-
}
上面的beanInfo就是Person类的完整信息。
第二步:获得方法描述器和属性描述器
-
@Test
-
public void demo(){
-
//调用Introspector中的getBeanInfo()方法,传入要获取信息的类的Class对象
-
BeanInfo beanInfo = Introspector.getBeanInfo(Person.class);
-
/*********************分割线****************************/
-
//获取方法描述器
-
MethodDescriptor[] methodDescriptors = beanInfo.getMethodDescriptors();
-
//获取属性描述器,调用getPropertyDescriptors方法,返回一个PropertyDescriptor数组
-
//其中一个PropertyDescriptor代表一个属性
-
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
-
}
之后就可以进行相应的操作了。学过JavaWeb应该都知道,表单有个自动封装数据的功能。其实它的实现就是内省技术,具体就举一个类似的例子。
要求:把要赋值的数据穿入Map,然后使用方法,把Map中的数据封装到JavaBean当中。
我们话不多说,直接开始写。依次是:创建Map->给Map赋值->创建对象->把Map中的值传给对象
-
@Test
-
public void demo(){
-
//创建一个Map
-
Map<String, String> p1 = new HashMap<String, String>();
-
//给Map赋值,其中key为Person中的变量名,value为要赋的值
-
p1.put("name", "zack");
-
p1.put("sex", "male");
-
//创建Person对象
-
Person person = new Person();
-
//给对象赋值,待实现方法
-
setData2Object(p1, person);
-
}
上面使用了一个setData2Object()方法,现在我们来实现一下这个方法:
-
private static void setData2Object(Map<String, String> map, Object obj)
-
throws Exception {
-
//获取BeanInfo
-
BeanInfo beanInfo = Introspector.getBeanInfo(person.getClass());
-
//获取属性描述器
-
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
-
//遍历描述器
-
for (PropertyDescriptor descriptor:propertyDescriptors) {
-
//通过属性名去Map中找对应的key
-
String name = descriptor.getName();
-
//找到对应的key后赋值
-
if (map.containsKey(name)){
-
String value = map.get(name);
-
//通过属性描述器获得写入属性的方法
-
Method writeMethod = descriptor.getWriteMethod();
-
//利用反射设置Value
-
writeMethod.invoke(person, value);
-
}
-
}
-
}
里面有一个东西前面没讲,就是通过属性描述器获得写入属性的方法。在api中,属性描述器有两个方法getWriteMethod、getReadMethod。简单来说就是获取get、set方法。之后利用反射就可以了。
再补充一句,内省属性描述器的个数不是通过属性的个数来算的,而是通过get、set方法。如:setAge、getName就是把前面的set和get去掉,获取一个属性名。