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

当我们需要封装从页面传递到后台的请求参数时,简单的方式就是使用一个工具类帮我们封装,省很多力气,还不容易出错。那接下来就简单介绍下这个BeanUtils工具类的实现原理,顺便重温下java内省机制。

BeanUtils的底层是使用java内省机制完成的,而内省的实现要依赖java 的反射机制

首先说明:为什么map中的value值的格式为String[]数组类型,因为表单中可能存在多选框,所以需要数组接收。

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

package com.wanghang.domain;

/**
 * User模型类
 * 
 * @author Hang.W
 * @version 1.0, 2016-12-24 12:53:10
 */
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
				+ "]";
	}

}
package com.wanghang.reflect;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.junit.Test;
import com.wanghang.domain.UserModel;

/**
 * 使用java反射机制来完成参数封装
 * 
 * @author Hang.W
 * @version 1.0, 2016-12-24 12:42:04
 */
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方法进行参数封装

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

package com.wanghang.reflect;

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;
import com.wanghang.domain.UserModel;

/**
 * 使用内省机制完成参数封装
 * 
 * @author Hang.W
 * @version 1.0, 2016-12-24 14:32:30
 */
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();
				// 反射执行方法
				writeMethod.invoke(userModel, map.get(name)[0]);
			}
		}
		System.out.println(userModel);
	}
}

 简单说明:

         内省机制,要通过属性描述器将类中的所有属性获取到,然后再进行比对,封装参数

具体实现:

1.      获取属性描述器对象

2.      通过属性描述器对象获取模型类中所有属性

3.      获取模型类中set()方法

4.      获取表单标签中name属性的值

5.      进行比对,反射执行方法,封装参数

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值