文章目录
- 以后所有的项目开发之中一定会存在有反射的应用, 以后使用的所有的开发框架里面到处都是反射的身影, 没有反射, 开发框架的存在意义就没有了.
- 反射与单级类操作设计要求
- 范例: 基本程序
- 单级自动VO设置实现
以后所有的项目开发之中一定会存在有反射的应用, 以后使用的所有的开发框架里面到处都是反射的身影, 没有反射, 开发框架的存在意义就没有了.
下面将主要结合简单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);
}
}