VO:值对象
问题引出
假如一个类中有无数的setter方法,开发人员在开发中需要一个一个的设定值,这样会浪费大量的时间,以及在操作中造成一些不必要的失误,所有通过反射,我们可以对程序进行简单的简化
例如:,输入字符串"属性名称:属性值|属性名称:属性值|属性名称:属性值|....",就可以将类中 的属性设置好。希望通过此程序实现任意的简单Java类的属性设置
分析
在Java语言中,类中的set和get方法是同get或set加上类中属性的首字母并大写加上属性第二个字母开始往后所有的部分,这样我们可以通过字符拼接的方法来构造一个和类中set和get方法名字相同的字符串,在运用反射的方式进行调用
代码实现
首先创建一个测试类,(此处所创建测试类的属性过少,只为说明问题)
package com.lin.dao;
/**
* Description:
* Author: llf
* Created in 2019/8/3 13:47
*/
public class Emp {
private String ename;
private String job;
private Dept dept=new Dept();
public Dept getDept() {
return dept;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
@Override
public String toString() {
return "Emp{" +
"ename='" + ename + '\'' +
", job='" + job + '\'' +
", dept=" + dept +
'}';
}
}
因为是多级VO操作,我们在该类中加入了另一个类的实例化对象
package com.lin.dao;
/**
* Description:
* Author: llf
* Created in 2019/8/3 13:47
*/
public class Emp {
private String ename;
private String job;
private Dept dept=new Dept();
public Dept getDept() {
return dept;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
@Override
public String toString() {
return "Emp{" +
"ename='" + ename + '\'' +
", job='" + job + '\'' +
", dept=" + dept +
'}';
}
}
在该类中再添加一个类的实例化对象,这样也就构成了三级VO,(还可在下一个类中继续添加,构成更深一层的VO,此处不再添加)
package com.lin.dao;
/**
* Description:
* Author: llf
* Created in 2019/8/3 14:46
*/
public class Company {
private String cname;
private String address;
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Company{" +
"cname='" + cname + '\'' +
", address='" + address + '\'' +
'}';
}
}
我们现在假定第一个类为核心,创建一个EmpAction类定位要操作的属性类型,我们此时要操作的类为Emp类,所有在其中实例化一个Emp类的对象,再创建一个方法执行JavaBean,提供属性的get方法,方便JavaBean的引用
package com.lin.dao;
import com.lin.bean.BeanOperation;
/**
* Description:
* Author: llf
* Created in 2019/8/3 13:49
*/
public class EmpAction {
private Emp emp=new Emp();
public void setValue(String value) throws Exception {
BeanOperation.setBeanValue(this,value);
}
public Emp getEmp() {
return emp;
}
}
再JavaBean中完成核心方法setBeanValue,主要作用为分割传进来的字符串进行分析,找到相应对象,再找到相应属性进行赋值,我们此时所设定的传入字符串格式为“属性名称:属性值|属性名称:属性值|属性名称:属性值|.”,
总体分析,我们可以对字符串先进行按“\\|”分割进行遍历,再进行“:”分割获得属性名称和属性对应的值,
package com.lin.bean;
import com.lin.dao.EmpAction;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Description:
* Author: llf
* Created in 2019/8/3 13:48
*/
public class BeanOperation {
public BeanOperation() {
}
/**
* 负责设置类中的属性操作
*
* @param actionObject 表示当前请求的程序类当前对象
* @param msg 属性的具体内容,格式为:"对象.属性名称:内容|对象.属性名称:内容..."
*/
public static void setBeanValue(Object actionObject, String msg) throws Exception {
String[] result = msg.split("\\|");
for (int i = 0; i < result.length; i++) {
String[] temp = result[i].split(":");
String attribute = temp[0];
String value = temp[1];
String[] fields = attribute.split("\\.");
if (fields.length > 2) {
// 确定当前操作的对象 不被下面的for循环移位,
Object curentObject = actionObject;
for (int j = 0; j < fields.length - 1; j++) {
// 对应getter的返回对象
// 循环结束一定能拿到最后一层的当前对象
curentObject = getObject(curentObject, fields[j]);
}
setObjectValue(curentObject, fields[fields.length-1], value);
} else {
Object curentObject = getObject(actionObject, fields[0]);
setObjectValue(curentObject, fields[1], value);
}
}
}
// 负责调用XXXAction类中的getter方法取得简单Java类对象
private static Object getObject(Object obj, String attribute) throws Exception {
//查找empaction中是否包含属性attribute,
Field field = obj.getClass().getDeclaredField(attribute);
if (field == null) {
field = obj.getClass().getField(attribute);
}
// 若未有属性,即该类中没有该对象,则也不可能有相应的get方法;直接返回
if (field == null) {
return null;
}
String methodName = "get" + initCap(attribute);
Method method = obj.getClass().getMethod(methodName);
return method.invoke(obj);
}
通过属性名程调用set方法,进行赋值,
private static void setObjectValue(Object obj, String attribute, String value) throws Exception {
Field field = obj.getClass().getDeclaredField(attribute);
if (field == null) {
field = obj.getClass().getField(attribute);
}
// 若未有属性,则也不可能有相应的set方法;直接返回
if (field == null) {
return;
}
String methodName = "set" + initCap(attribute);
Method setmethod = obj.getClass().getMethod(methodName, field.getType());
setmethod.invoke(obj, value);
}
//将字符串首字母大写
private static String initCap(String str) {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
}
测试主类
package com.lin.main;
import com.lin.dao.EmpAction;
/**
* Description:
* Author: llf
* Created in 2019/8/3 14:27
*/
public class TestDemo {
public static void main(String[] args) throws Exception {
String value = "emp.ename:feval|emp.job:Java Coder|emp.dept.dname:教务部|emp.dept.company.cname:xi'an technology" ;
EmpAction empAction=new EmpAction();
empAction.setValue(value);
System.out.println(empAction.getEmp());
}
}
运行结果
Emp{ename='feval', job='Java Coder', dept=Dept{dname='学生', loc='null', company=Company{cname='xi'an technology', address='null'}}}