通常业务中经常会遇到需要将一些键值对封装到javaBean中的情况,就在昨天抽空利用反射实现了map键值对为输入,封装指定bean的方法,因为之前在网上看到过相关的设计代码,所以算是对记忆的实现吧,记录一下以后也许用的到。
大致设计思路就是说传入bean的class对象以及键值对的map对象,通过反射map中的key去找相应的bean中的set值的方法,最后完成封装。
首先先建立bean模型:
/**
* @ClassName: TestBean
* @Description: TODO
* @Author: Michael
* @Date: 2020-3-12 上午 9:49
* @Version: 1.0
*/
public class TestBean {
private int id;
private String name;
private double price;
private long age;
private TestBean2 testBean2;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public long getAge() {
return age;
}
public void setAge(long age) {
this.age = age;
}
public TestBean2 getTestBean2() {
return testBean2;
}
public void setTestBean2(TestBean2 testBean2) {
this.testBean2 = testBean2;
}
@Override
public String toString() {
return "TestBean{" +
"id=" + id +
", name='" + name + '\'' +
", price=" + price +
", age=" + age +
", testBean2=" + testBean2 +
'}';
}
}
实用起见,这里做了个级联的引用属性,下面是另外的两个引用的Bean模型:
/**
* @ClassName: TestBean2
* @Description: TODO
* @Author: Micheal
* @Date: 2020-3-12 上午 9:51
* @Version: 1.0
*/
public class TestBean2 {
private String name;
private TestBean3 testBean3;
@Override
public String toString() {
return "TestBean2{" +
"name='" + name + '\'' +
", testBean3=" + testBean3 +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public TestBean3 getTestBean3() {
return testBean3;
}
public void setTestBean3(TestBean3 testBean3) {
this.testBean3 = testBean3;
}
}
以及
/**
* @ClassName: TestBean3
* @Description: TODO
* @Author: Michael
* @Date: 2020-3-12 上午 9:51
* @Version: 1.0
*/
public class TestBean3 {
private String name;
@Override
public String toString() {
return "TestBean3{" +
"name='" + name + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
上面的Bean就建完了,下面就是反射部分得代码了:
首先建立主类主要负责外界调用以及返回对象,具体的数据处理放在另一个方法里面
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
/**
* @ClassName: BeanUtilFactory
* @Description: TODO
* @Author: Michael
* @Date: 2020-3-12 上午 9:53
* @Version: 1.0
*/
public class BeanUtilFactory {
public static <T>T addToBean(Class<?> clazz, Map<String, String> map){
Object object=null;
try {
object=clazz.getDeclaredConstructor().newInstance();
BeanUtil.loadBean(object,map);
} catch (Exception e) {
e.printStackTrace();
}
return (T)object;
}
}
这个是主要数据处理的类:
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
/**
* @ClassName: BeanUtil
* @Description: TODO
* @Author: Michael
* @Date: 2020-3-12 上午 10:03
* @Version: 1.0
*/
public class BeanUtil {
public static void loadBean(Object Object, Map<String, String> map) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
for (Map.Entry entry : map.entrySet()) {
Object currentObject=Object;
String paramName = entry.getKey().toString();
if (entry.getKey().toString().indexOf(".") != -1) {
String[] keys = entry.getKey().toString().split("\\.");
for (int i = 0; i < keys.length - 1; i++) {
Field field = currentObject.getClass().getDeclaredField(keys[i]);
Method getMethod = currentObject.getClass().getDeclaredMethod("get" + StringUtil.initCaseUp(keys[i]));
if (getMethod.invoke(currentObject) == null) {
Method method = currentObject.getClass().getDeclaredMethod("set" + StringUtil.initCaseUp(keys[i]),field.getType());
method.invoke(currentObject, field.getType().getDeclaredConstructor().newInstance());
}
currentObject = getMethod.invoke(currentObject);
}
paramName = keys[keys.length - 1];
}
Field field = currentObject.getClass().getDeclaredField(paramName);
String type = field.getType().getName();
Method method = null;
if (type.equalsIgnoreCase("String") || type.equalsIgnoreCase("java.lang.String")) {
method = currentObject.getClass().getDeclaredMethod("set" + StringUtil.initCaseUp(paramName), java.lang.String.class);
method.invoke(currentObject, entry.getValue().toString());
} else if (type.equalsIgnoreCase("double") || type.equalsIgnoreCase("java.lang.Double")) {
method = currentObject.getClass().getDeclaredMethod("set" + StringUtil.initCaseUp(paramName), java.lang.Double.class);
method.invoke(currentObject, Double.parseDouble(entry.getValue().toString()));
} else if (type.equalsIgnoreCase("boolean") || type.equalsIgnoreCase("java.lang.Boolean")) {
method = currentObject.getClass().getDeclaredMethod("is" + StringUtil.initCaseUp(paramName), java.lang.Boolean.class);
method.invoke(currentObject, Boolean.getBoolean(entry.getValue().toString()));
} else if (type.equalsIgnoreCase("long") || type.equalsIgnoreCase("java.lang.Long")) {
method = currentObject.getClass().getDeclaredMethod("set" + StringUtil.initCaseUp(paramName), java.lang.Long.class);
method.invoke(currentObject, Long.parseLong(entry.getValue().toString()));
} else if (type.equalsIgnoreCase("int") || type.equalsIgnoreCase("java.lang.Integer")) {
method = currentObject.getClass().getDeclaredMethod("set" + StringUtil.initCaseUp(paramName), int.class);
method.invoke(currentObject, Integer.parseInt(entry.getValue().toString()));
} else if (type.equalsIgnoreCase("float") || type.equalsIgnoreCase("java.lang.Float")) {
method = currentObject.getClass().getDeclaredMethod("set" + StringUtil.initCaseUp(paramName), float.class);
method.invoke(currentObject, Float.parseFloat(entry.getValue().toString()));
}
}
}
}
最后附加其中用到的字符串首字母大写的工具类:
/**
* @ClassName: StringUtil
* @Description: TODO
* @Author: Michael
* @Date: 2020-3-12 上午 10:27
* @Version: 1.0
*/
public class StringUtil {
public static String initCaseUp(String demo){
if(demo==null)
return demo;
else if(demo.equals(""))
return demo;
else
return demo.substring(0,1).toUpperCase()+demo.substring(1);
}
}