- 属性是私有的;
- 有无参的public构造方法;
- 对私有属性提供public的getXxx方法和setXxx方法; 符合这些特征的类,被称为JavaBean;而JDK提供了一套API用来访问某个属性的getter/setter方法,这些API存放在java.beans中,这就是内省。
-
一个类有两种状态(编译和运行),通常我们是在编译状态来获取类的信息,也就是new一个实例出来,然后通过该实例来获取类内部的信息。若需要在类运行时动态的获取类的信息,则需要用到反射。
-
反射是在运行中,对任意一个类,能够获取到这个类所有的属性和方法。
-
内省是通过反射来实现的,用BeanInfo来暴露一个bean的属性、方法和事件,以后我们就可以操纵该JavaBean的属性,其包括的主要类有:Introspector、BeanInfo、PropertyDescriptor
-
内省对javaBean属性、方法的处理方式。
-
反射可以操作各种类的属性,而内省只是通过反射来操作JavaBean的属性;
-
内省设置属性值会调用setter方法,而反射可以直接调用Field;
-
反射看到.class的所有,看到的是客观事实,而内省更像是主观的判断,比如看到getName()内省就会认为这个类有name字段,但实际上不一定有name。
-
通过内省可以获取到bean的getter和setter。
-
Introspector提供了一系列的getBeanInfo 方法,可以拿到一个JavaBean的所有核心信息。
-
通过BeanInfo的getPropertyDescriptors和getMethodDescription方法可以拿到JavaBean的字段信息列表和getter和setter的方法列表。
-
PropertyDescriptors 可以根据字段直接获得该字段的 getter 和 setter 方法。
-
MethodDescriptors 可以获得方法的元信息,比如方法名,参数个数,参数字段类型等。
-
PropertyDescriptor类表示JavaBean类通过存储器导出一个属性。主要方法:
- getPropertyType(),获得属性的Class对象;
- getReadMethod(),获得用于读取属性值的方法;getWriteMethod(),获得用于写入属性值的方法;
- hashCode(),获取对象的哈希值;
- setReadMethod(Method readMethod),设置用于读取属性值的方法;
- setWriteMethod(Method writeMethod),设置用于写入属性值的方法。
- JavaBean
/**
* 部门
* @author HC
*
*/
public class Dept {
/**
* 部门编号
*/
private Integer deptno;
/**
* 部门名称
*/
private String dname;
/**
* 部门地址
*/
private String loc;
public Dept() {
}
public Dept(Integer deptno, String dname, String loc) {
this.deptno = deptno;
this.dname = dname;
this.loc = loc;
}
public Integer getDeptno() {
return deptno;
}
public void setDeptno(Integer deptno) {
this.deptno = deptno;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
@Override
public String toString() {
return "Dept{" +
"deptno=" + deptno +
", dname='" + dname + '\'' +
", loc='" + loc + '\'' +
'}';
}
}
- 测试方法
public static void main(String[] args) throws IntrospectionException {
// 获取整个Bean的信息
// BeanInfo beanInfo= Introspector.getBeanInfo(user.getClass());
// 在Object类时候停止检索,可以选择在任意一个父类停止
BeanInfo beanInfo = Introspector.getBeanInfo(Dept.class, Object.class);
System.out.println("所有属性描述:");
// 获取所有的属性描述
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
System.out.println(pd.getName());
}
System.out.println("所有方法描述:");
MethodDescriptor[] mds = beanInfo.getMethodDescriptors();
for (MethodDescriptor md : mds) {
System.out.println(md.getName());
}
}
说明:
- getPropertyDescriptors(),获得属性的描述,可以采用遍历BeanInfo的方法,来查找、设置类的属性。
- 结果
- 测试代码
public static void main(String[] args) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
Dept dept = new Dept(10, "sales", "NewYork");
BeanInfo beanInfo = Introspector.getBeanInfo(Dept.class);
//获取属性描述符
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
System.out.println(pd.getName() + "=" + pd.getReadMethod().invoke(dept));
}
PropertyDescriptor dname = new PropertyDescriptor("dname", Dept.class);
System.out.println("内省获取的dname为:" + dname.getReadMethod().invoke(dept));
//修改属性的值
dname.getWriteMethod().invoke(dept, "research");
System.out.println("内省修改的dname为:" + dept.getDname());
}
- 结果