反射自省的理解

本文介绍了Java中的反射和自省机制,通过Introspector获取BeanInfo,然后利用PropertyDescriptor进行属性的读写操作。示例代码展示了如何使用自省获取和设置JavaBean的属性值,以及对比了更直接的反射操作方式。此外,还提及了对非公开成员的访问策略。
摘要由CSDN通过智能技术生成

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文档,目前就更新这些,会继续学习更新。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值