內省(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.      進行比對,反射執行方法,封裝參數


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