内省(BeanUtils) + 反射(简单应用实现原理)

当我们需要封装从页面传递到后台的请求参数时,简单的方式就是使用一个工具类帮我们封装,省很多力气,还不容易出错。那接下来就简单介绍下这个BeanUtils工具类的实现原理,顺便重温下Java内省机制。
BeanUtils的底层是使用java内省机制完成的,而内省的实现要依赖java 的反射机制
首先说明:为什么map中的value值的格式为String[]数组类型,因为表单中可能存在多选框,所以需要数组接收。

一:那么首先使用java反射来完成请求参数的封装

/**
 * User模型类
 */
public class UserModel {

	private String username;

	private String password;

	public UserModel() {
	}

	public UserModel(String username, String password) {
		this.username = username;
		this.password = password;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	@Override
	public String toString() {
		return "UserModel [username=" + username + ", password=" + password + "]";
	}

}
import java.lang.reflect.Method;  
import java.util.HashMap;  
import java.util.Map;  
import java.util.Set;

import org.junit.Test;  


  
/** 
 * 使用java反射机制来完成参数封装 
 */  
public class Reflect {  
  
    /** 
     * 通过反射注入参数 
     *  
     * @throws Exception 
     */  
    @Test  
    public void reflect() throws Exception {  
        // 创建一个Map集合,封装(假设从页面传递的)参数  
        Map<String, String[]> map = new HashMap<String, String[]>();  
        map.put("username", new String[] {"张三"});  
        map.put("password", new String[] {"123"});  
          
        // 创建User模型类  
        UserModel userModel = new UserModel();  
          
        // 获取map中所有的key  
        Set<String> keys = map.keySet();  
          
        // 通过反射获取UserModel类中所有的方法(包括私有)  
        Method[] methods = userModel.getClass().getDeclaredMethods();  
          
        // 判断方法名是否和 "set" + 从页面表单获取name属性的值相同  
        for(String key : keys) {  
            // 从页面上获取的name属性的值加上"set"  
            String newKey = "set" + key;  
            for (Method method : methods) {  
                // 获取方法名  
                String name = method.getName();  
                // 判断  
                if(newKey.equalsIgnoreCase(name)) {  
                    // 相同,反射执行方法 invoke("对象", "参数")  
                    method.invoke(userModel, map.get(key)[0]);  
                }  
            }  
        }  
        System.out.println(userModel);  
    }  
}  
简单说明:
         我们要封装从表单标签(例:用户名:<inputtype=”text” name=”username”>)传递的参数,那么我们就可以从表单中name属性作为切入点,使用反射机制,封装参数。
具体实现:
1.      首先获取表单标签name属性中的值,
2.      获取对象模型类中的所有方法
3.      进行比对,执行setXXX方法进行参数封装

二:使用内省方式封装参数

import java.beans.BeanInfo;  
import java.beans.Introspector;  
import java.beans.PropertyDescriptor;  
import java.lang.reflect.Method;  
import java.util.HashMap;  
import java.util.Map;  
import org.junit.Test;  
  
/** 
 * 使用内省机制完成参数封装 
 *  
 */  
public class Introspect {  
  
    /** 
     * 通过内省封装参数 
     *  
     * @throws Exception 
     */  
    @Test  
    public void introspect() throws Exception {  
        // 创建一个Map集合,封装(假设从页面传递的)参数  
        Map<String, String[]> map = new HashMap<String, String[]>();  
        map.put("username", new String[] {"张三"});  
        map.put("password", new String[] {"123"});  
          
        // 创建User模型类  
        UserModel userModel = new UserModel();  
          
        // 获取BeanInfo对象  
        BeanInfo beanInfo = Introspector.getBeanInfo(UserModel.class);  
          
        // 通过BeanInfo对象获取所有的属性描述器(说白了,就是获取所有的属性)  
        PropertyDescriptor[] propertyDescriptor = beanInfo.getPropertyDescriptors();  
        for (PropertyDescriptor prop : propertyDescriptor) {  
            //System.out.println(prop);  
            // 通过属性描述器,获取写方法  
            Method writeMethod = prop.getWriteMethod();  
            if(writeMethod != null) {  
                // 获取所有属性的名字(与表单标签中填写的相同)  
                String name = prop.getName();  
                System.out.println(name);
                // 反射执行方法  
                writeMethod.invoke(userModel, map.get(name)[0]);  
            }  
        }  
        System.out.println("----------------");
        System.out.println(userModel);  
    }  
}  

简单说明:

         内省机制,要通过属性描述器将类中的所有属性获取到,然后再进行比对,封装参数
具体实现:
1.      获取属性描述器对象
2.      通过属性描述器对象获取模型类中所有属性
3.      获取模型类中set()方法
4.      获取表单标签中name属性的值
5.      进行比对,反射执行方法,封装参数


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章