在Spring 框架中 很常见根据参数名称自动赋值的反射操作 例如:Spring MVC 中前台请求具体的Controller 而具体的方法的入参可以根据参数名自动复制。
JDK提供的反射 没用这样的功能 仅提供了 按参数顺序顺序赋值。
而Spring 则使用了第三方的字节码解析工具(asm) 从字节码中读取各个方法的参数名称 具体实现可 查看LocalVariableTableParameterNameDiscoverer 类
本人在项目的一次使用
主要是为了将 保存数据 和修改流程状态放在同一个事务中处理,然而 保存 和修改状态又都是可以单独发起的前台请求
所有 保存 数据的请求包含了 修改流程状态的URL 根据spring的 url与Controller的映射发现类(RequestMappingHandlerMapping)可以找到对应的Controller
然后通过上面提到的具体的参数发现类 给 具体的Controller的入参赋值 然后调起后续修改流程的状态
/**
*
* @Description: 根据url 找到对应的controller的某一方法的调起实现 主要功能是匹配参数
* @param jsonparam 调用后续操作方法是需要的参数 建议使用json 这有助于解耦
* @param method 根据spring的 url与controller对应关系 获得的HandlerMethod 就是后续操作需要调起的Method对象
* @return
* @throws Exception
*/
public static Object invokeCallMethod(Object jsonparam, HandlerMethod method)
throws Exception {
Method methodtarget = method.getMethod();
//一般url对应的controller的方法不可能非public的 或者反射不可访问的 此段留作备用
//ReflectionUtils.makeAccessible(methodtarget);
String[] parameterNames = discoverer.getParameterNames(methodtarget);
Object[] param = new Object[parameterNames.length];
JSONObject jsonObject = JSONObject.fromObject(jsonparam);
/**
* 准备调起methodtarget的参数 所有参数默认使用的是string类型
* json传递的数据类型:spfid:1 对用的后台参数为int类型 spfid:"1"用的后台参数为string类型
*
* 若程序报 参数不匹配 的异常的 请检查后台控制层的参数类型是否为string类型
*
*/
for (int i = 0; i < parameterNames.length; i++) {
param[i] = jsonObject.get(parameterNames[i])+"";
}
Object targetObject = method.createWithResolvedBean().getBean();
return methodtarget.invoke(targetObject, param);
}