内省,以及内省的用处

在实际编程中,我们常常需要一些用来包装值对象的类,例如Student、Employee、Order,这些类中往往没有业务方法,只是为了把需要处理的实体对象进行封装,有这样的特征:
属性都是私有的;
有无参的public构造方法;
对私有属性根据需要提供 公有的getXxx方法以及setXxx方法;例如属性名称为name,则有getName方法返回属性name值,setName方法设置name值;注意方法的名称通常是get或set加上属性名称,并把属性名称的首字母大写;这些方法称为getters/setters;getters必须有返回值没有方法参数;setter值没有返回值,有方法参数;

符合这些特征的类,被称为JavaBean;

内省(Inspector)机制就是基于反射的基础,Java语言对Bean类属性、事件的一种缺省处理方法。

注意:只要类中有getXXX方法,或者setXXX方法,或者同时有getXXX及setXXX方法,其中getXXX方法没有方法参数,有返回值;setXXX方法没有返回值,有一个方法参数;那么内省机制就认为XXX为一个属性;
内省机制检索属性时,是根据getter和setter方法确认属性名字,而不是根据类里声明的属性名决定;

package com.yh.reflex;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;

/**
 * --内省
 *
 */
public class Demo03 {
	
	public static void main(String[] args)throws Exception {
		String className = "com.yh.reflex.Student";
		Class<?> cls = Class.forName(className);
		System.out.println(cls);
		
		BeanInfo studentInfo = Introspector.getBeanInfo(cls);
		PropertyDescriptor[] propertys = studentInfo.getPropertyDescriptors();//属性;get,set
		
		for(PropertyDescriptor p : propertys) {
			System.out.println(p.getName());
			System.out.println("\t"+p.getPropertyType());//属性类型
			System.out.println("\t"+p.getReadMethod());//get方法
			System.out.println("\t"+p.getWriteMethod());//set方法
		}
	}
	
}

内省的用处:
比如在JDBC中,可通过内省的方式对在对象之间进行属性的复制

package com.yh.util;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * 用来复制属性值;相当于cn.hutool.core.bean.BeanUtil.copyProperties
 *
 */
public class BeanUtil {
	
	private BeanUtil() {}
	
	/**
	 * 
	 * @param sourceBean 被复制的对象;已知
	 * @param targetBean 复制到的对象;目标
	 * @param ignoreProperties 哪些属性不被复制
	 */
	public static void copy(Object sourceBean,Object targetBean,String...ignoreProperties) {
		Set<String> ignorePropertiesSet = new HashSet<>();
		if(ignoreProperties!=null){
			java.util.Collections.addAll(ignorePropertiesSet, ignoreProperties);
		}
		Class<?> sourceClass = sourceBean.getClass();
		Class<?> targetClass = targetBean.getClass();
		try {
			BeanInfo sourceInfo = Introspector.getBeanInfo(sourceClass);
			PropertyDescriptor[] propertys = sourceInfo.getPropertyDescriptors();
			Map<String, PropertyDescriptor> map = new HashMap<String, PropertyDescriptor>();
			for(PropertyDescriptor p : propertys) {
				map.put(p.getName(), p);
			}
			BeanInfo targetInfo = Introspector.getBeanInfo(targetClass);
			propertys = targetInfo.getPropertyDescriptors();
			for(PropertyDescriptor p : propertys) {
				if(p.getWriteMethod()==null) {//如果目标bean的属性没有setter,跳过,进入下一个属性
					continue;
				}
				if(ignorePropertiesSet.contains(p.getName())) {//如果目标bean的属性在忽略的属性中,跳过
					continue;
				}
				PropertyDescriptor sourceProperty = map.get(p.getName());
				if(sourceProperty == null || sourceProperty.getReadMethod() == null) {//如果原对象没有对应的getter方法,跳过
					continue;
				}
				//以上条件都成立后,将原对象要复制的属性的值进行获取
				Object obj = sourceProperty.getReadMethod().invoke(sourceBean);
				//将该值复制给目标对象
				if(obj != null) {
					p.getWriteMethod().invoke(targetBean, obj);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值