反射与简单java类

以后所有的项目开发之中一定会存在有反射的应用, 以后使用的所有的开发框架里面到处都是反射的身影, 没有反射, 开发框架的存在意义就没有了.

下面将主要结合简单Java类来进行反射开发的深入研究, 同时这些也是后期 SpringMVC, Struts 这些框架的主要工作原理.

反射与单级类操作设计要求

如果现在有一个简单Java类, 那么这个简单Java类中的属性按照原始的做法一定要通过setter才可以设置, 取得继续使用getter (不关心此处)

范例: 基本程序

package com.beyond.dhl;

public class Emp {
    
    
	private String ename;
	private String job;
	
	public void setEname(String ename) {
    
    
		this.ename = ename;
	}
	public void setJob(String job) {
    
    
		this.job = job;
	}
	public String getEname() {
    
    
		return ename;
	}
	public String getJob() {
    
    
		return job;
	}
}

现在 Emp 程序类中存在有无参构造的方法, 如果按照传统调用, 则编写如下:

package com.beyond.dhl;

public class TestDemo {
    
    
	public static void main(String[] args) {
    
    
		Emp vo = new Emp();
		vo.setEname("SMITH");
		vo.setJob("CLERK");
		System.out.println(vo);
	}
}

但是这个时候觉得这样操作太麻烦了, 假设一个类中存在有几十个属性, 那么要写几十次的 setter 方法. 我希望可以简化一些, 例如, 给你一个字符串, 格式" 属性名称: 内容 | 属性名称: 内容 | …", 能够按照这样的形式将内容全部设置到属性里面.

package com.beyond.dhl;

import com.beyond.util.BeanOperation;
import com.beyond.vo.Emp;

public class EmpAction {
    
    
	private Emp emp = new Emp();
	public void setValue(String val) throws Exception {
    
      // 设置属性内容
		// 之所以要传递一个 this, 主要是将 EmpAction 的类对象传递到方法里面
		// 因为给定的标记: emp.ename:smith, 而emp 应该对应的是 getEmp() 方法5
		BeanOperation.setBeanValue(this, val);
	}
	public Emp getEmp() {
    
    
		return emp;
	}
}

package com.beyond.dhl;

public class TestDemo {
    
    
	public static void main(String[] args) throws Exception {
    
    
		String value = "emp.ename:smith|emp.job:clerk" ;
		EmpAction empAction = new EmpAction();		
		empAction.setValue(value);
		System.out.println(empAction.getEmp());
	}
}

通过以下的程序可以实现任意的简单Java类的属性设置

单级自动VO设置实现

现在所有的操作都是通过 TestDemo类调用EmpAction类实现, 而 EmpAction类的主要作用在于定位要操作属性的类型. 同时该程序应该符合于所有的简单Java类开发形式, 那么也就意味着我们的设计必须有一个单独的类定义, 即建立一个 com.beyond.util.BeanOperation 程序类.

package com.beyond.util;

/**
 * 本类主要负责实现自动的VO匹配处理操作, 本身不需要通过实例化对象完成, 所以构造方法私有化
 * @author DHL
 */

public class BeanOperation {
    
    
	private BeanOperation() {
    
    }
	
	
	/**
	 * 负责设置类中的属性操作
	 * @param actionObject 表示当前发出设置请求的程序类的当前对象
	 * @param msg	所有的属性的具体内容, 格式"属性名称:内容|属性名称:内容|..."
	 * @throws Exception 
	 */
	public static void setBeanValue(Object actionObject,String msg) throws Exception {
    
    
		// 如果要想进行内容的设置, 那么必须要求将字符串拆分(此处不关心验证)
		String result [] = msg.split("\\|");
		for (int x = 0; x < result.length; x++) {
    
      // 此时每次执行的格式:"属性名称:属性内容"
			// 需要针对于给定的属性名称和内容进行一次拆分
			String temp [] = result[x].split(":");
			String attribute = temp[0] ; // 属性名称, 包括了"XxxAction属性和具体简单java类的属性"
			String value = temp[1] ;  // 接收具体的属性内容
			String field [] = attribute.split("\\.");   //拆分属性的信息
			Object currentObject = ObjectUtils.getObject(actionObject, field[0]);
			ObjectUtils.setObject(currentObject, field[1], value);
		}
		
	}
}

由于这种 Bean 的处理操作里面肯定需要被重复取出对象的信息, 所以我们需要再次准备两个程序类 : StringUtils, 负责字符串的处理操作, 毕竟属性的名称首字母需要大写; 然后需要一个对象的具体操作(取得对象, 设置对象内容)

package com.beyond.util;

/**
 * 针对于字符串进行的处理操作
 * @author DHL
 */

public class StringUtils {
    
    
	private StringUtils() {
    
    }
	
	/**
	 * 首字母大写
	 * @param str 要处理的字符串
	 * @return 操作后的内容
	 */
	public static String initcap(String str) {
    
    
		return str.substring(0,1).toUpperCase()+str.substring(1);
		
	}
}

package com.beyond.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 本类的主要功能是根据属性名称调用相应类中的getter,setter 方法
 * @author DHL
 *
 */
public class ObjectUtils {
    
    
	private ObjectUtils() {
    
    }
	
	/**
	 * 负责调用指定类中的 getter 方法
	 * @param wrapObject 表示要调用的方法所在类对象
	 * @param attribute	表示属性名称
	 * @return	调用对象的结果
	 * @throws Exception 
	 */
	public static Object getObject(Object wrapObject, String attribute) throws Exception {
    
    
		String methodName = "get" + StringUtils.initcap(attribute);
		// 调用指定属性的Field对象,目的是取得对象类型, 如果没有此属性也就意味着该操作无法继续了
		Field field = wrapObject.getClass().getDeclaredField(attribute);
		if (field == null) {
    
      // 给你第二次取得的机会, 万一某些属性是需要通过父类取得呢
			field = wrapObject.getClass().getField(attribute);
		}
		if (field == null) {
    
      // 两次操作都无法取得对应的成员对象
			return null;  // 该属性一定不存在
		}
		
		Method method = wrapObject.getClass().getMethod(methodName);
		return method.invoke(wrapObject);
	}
	
	
	/**
	 * 根据指定的类对象设置指定类的属性, 调用setter方法
	 * @param wrapObject 属性所在类的实例化对象
	 * @param attribute	属性名称
	 * @param attribute	属性内容
	 * @return
	 * @throws Exception
	 */
	public static Object setObject(Object wrapObject, String attribute, String value) throws Exception {
    
    
		
		// 调用指定属性的Field对象,目的是取得对象类型, 如果没有此属性也就意味着该操作无法继续了
		Field field = wrapObject.getClass().getDeclaredField(attribute);
		if (field == null) {
    
      // 给你第二次取得的机会, 万一某些属性是需要通过父类取得呢
			field = wrapObject.getClass().getField(attribute);
		}
		if (field == null) {
    
      // 两次操作都无法取得对应的成员对象
			return null;  // 该属性一定不存在
		}
		
		String methodName = "set" + StringUtils.initcap(attribute);
		
		Method method = wrapObject.getClass().getMethod(methodName,field.getType());
		
		return method.invoke(wrapObject,value);
	}
}


在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Beyond_Nothing/article/details/112149964
今日推荐