(模拟Java内省的功能)
★ 准备工作
定义两个Model类,里面所有的属性都是private的,然后为每个属性提供getter和setter方法;
再准备一个Map,map的key值都是类里面的属性字段的字符串表示,值任意。
★ 真正的工作
设计一个方法Object getModel(Map map,Class cls),传入一个包含所有值的Map,然后再传入Model类的class,那么返回Model类的实例,这个实例里面已经包含好了所有相关的数据。也就是把Map中的数据通过反射,设置回到Model类实例中。
Beanutils用了魔术般的反射技术!
需求分析:给你一个HashMap集合,将他直接封装成相应的值对象!(听起来很强!今天我们来看看他的底层代码是如何实现的!)
UserModel值对象:
package cn.hncu.MyBeanUtils;
import java.io.Serializable;
public class UserModel implements Serializable{
private String uuid;
private String name;
private int age;
private String pwd;
public UserModel() {
super();
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
UserModel other = (UserModel) obj;
if (uuid == null) {
if (other.uuid != null)
return false;
} else if (!uuid.equals(other.uuid))
return false;
return true;
}
@Override
public String toString() {
return uuid + ", " + name + ", " + age+", pwd:"+pwd;
}
}
BookModel值对象:
package cn.hncu.MyBeanUtils;
import java.io.Serializable;
public class UserModel implements Serializable{
private String uuid;
private String name;
private int age;
private String pwd;
public UserModel() {
super();
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
UserModel other = (UserModel) obj;
if (uuid == null) {
if (other.uuid != null)
return false;
} else if (!uuid.equals(other.uuid))
return false;
return true;
}
@Override
public String toString() {
return uuid + ", " + name + ", " + age+", pwd:"+pwd;
}
}
MyBeanUtils工具类(我的BeanUtils工具类–利用底层代码来实现apache公司中的一个BeanUtils工具类):
package cn.hncu.MyBeanUtils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
//一个很强的工具---能够将map中的元素封装成相对应的值对象!
public class MyBeanUtils {
//BeanUtils是阿帕奇公司的一个主要利用了类反射做出来的一个很强的工具!接下来我来把他的底层代码给实现掉,看看他的强大之处在哪里
//主要类中调用了populate()方法来实现功能代码
//map是已经封装好的HashMap集合,里面的数据都是存在的,cls也是从已知值对象的方法名(例如:UserModel.class)
public static<T> T populate(Class<T> cls,Map<String, Object> map) throws Exception {
Object obj = cls.newInstance();//值对象必须规范(即值对象中必须有一个空参构造方法!)
//获取cls中的所有属性
Field flds[] = cls.getDeclaredFields();
//遍历属性值与map中的属性值进行比较,看是否存在该属性
for(Field fld:flds){
//拿到每个变量值(包括私有变量)进行与map中的key进行比较,看是否能够找到相匹配的
Object value = map.get(fld.getName());
if(value == null){
//说明在map集合中找不到在值对象中与之相匹配的属性值
System.out.println(fld.getName()+"不存在,为空值!");
continue;
}
//如果存在则找到相应的setter方法进行设置值的操作(给属性赋值的操作)
//拿到属性值对应的方法名!!!!!很强的(这里也就是设计模中提到的值对象模板规范的原因)
String methodName = "set"+fld.getName().substring(0, 1).toUpperCase()+fld.getName().substring(1);
//再通过方法名字加上属性(成员变量)类型找到该属性值设置属性值的方法进行属性设置
Method m = cls.getMethod(methodName, fld.getType());
m.invoke(obj, value);
}
return (T) obj;
}
}
Client演示类:
package cn.hncu.MyBeanUtils;
import java.util.HashMap;
import java.util.Map;
public class Client {
public static void main(String[] args) {
Map<String, Object> map = new HashMap<String, Object>();
//给map集合中添加元素---以后这种值直接从前台页面中通过getParameterMap()直接拿到整个集合对象
//模拟前台页面!!!!
map.put("uuid", "A001");
map.put("name", "Java");
map.put("age", 15);
//map.put("pwd", "1234");
//调用那个工具类,这里首先演示我们自己写的工具类---MyBeanUtils工具类
try {
UserModel user = MyBeanUtils.populate(UserModel.class, map);
System.out.println(user);
System.out.println("------------------");
BookModel book = MyBeanUtils.populate(BookModel.class, map);
System.out.println(book);
} catch (Exception e) {
e.printStackTrace();
}
}
}
代码实现: