1.反射:通过类的字节码去获得类的属性和方法。
2.自省:通过javabean 去改变正在运行类的属性值和方法描述。
//代码来来自http://t.csdn.cn/JHOow,自省我写的可能不好,就抄了一遍别人的加深理解
package cn.rocket.study.introspector;
import java.sql.Date;
/**
* @author rocket
*
*/
public class Person {
private String name ;
private Integer age ;
private Date birthday = new Date(System.currentTimeMillis()) ;
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Person(String name,Integer age){
this.name = name ;
this.age = age ;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
//为了加深影响抄了一遍别人的代码
package cn.rocket.study.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;
public class IntrospectorTest {
public static void main(String[] args) throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
Person person = new Person("rocket", 20);
System.out.println("原始数据是:"+person);
String propertyName = "name" ;
Object val = getProperty(person, propertyName);
System.out.println("通过内省获取JavaBean属性:name = "+val);
Object value = "Jack" ;
setProperty(person, propertyName, value);
System.out.println("通过内省设置JavaBean属性后:name="+getProperty(person, propertyName));
}
//通过内省操作获取JavaBean属性值
private static Object getProperty(Object obj, String propertyName)
throws IntrospectionException, IllegalAccessException, InvocationTargetException {
/*
//使用比较简单的方式
PropertyDescriptor proDescriptor = new PropertyDescriptor(propertyName,obj.getClass());
Method getMethod = proDescriptor.getReadMethod() ;
Object val = getMethod.invoke(obj);//通过反射调用方法
return val;
*/
//使用比较笨的方式
Object returnVal = null ;
BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass()) ;
PropertyDescriptor[] pros = beanInfo.getPropertyDescriptors() ;
for(PropertyDescriptor p:pros){
if(p.getName().equals(propertyName)){
returnVal = p.getReadMethod().invoke(obj);
break ;
}
}
return returnVal ;
}
//通过内省操作设置JavaBean属性值
private static void setProperty(Object obj, String propertyName, Object value)
throws IntrospectionException, IllegalAccessException, InvocationTargetException {
PropertyDescriptor proDescriptor = new PropertyDescriptor(propertyName,obj.getClass());
Method setMethod = proDescriptor.getWriteMethod() ;//通过反射调用方法
setMethod.invoke(obj, value);
}
}
从自省代码中,明显的可以看出过程为:
获取类的字节码信息转换成beaninfo,再获得属性描述,然后利用属性描述的方法setter和getter去实现改变当前运行对象的属性。自省中获取对象的方法特别愚蠢,学习可以,但是实操应该选用下面的利用类字节码路径获取。
//测试代码
package test.myreflect;
class Pepole{
public String name;
protect int birthday;
public void set_name(String name){
this.name=name;
}
}
public class test{
public static void main(String[] argc){
//获取class对象
Class class=Class.forName("test.myreflect");
//获取字段 ,Field[] array=class.getFeild()可以获得所有成员属性存储在array数组中
Field name=class.getField("name");
Field birthday=class.getFieid("birthday");
//获取方法
Method set_name=class.getMethod("set_name",String.class);
//获得对象实例
Object obj = class.getConstructor().newInstance();
//实例操作
name.set(obj,"zs");
set_name.invoke(obj."ls")
//对于非公开的成员属性,方法可以暴力破解
m.setAccessible(true);
//比如birthday.set(obj,100);
}
}
这是一个非常简单的使用,具体的使用建议去看一看反射的原理和java文档,目前就更新这些,会继续学习更新。