实战Java的反射机制
众所周知,Java要调用某个对象的方法首先需要对象实例化后才能调用。
而实例化对象常见的就是new执行和spring(DI)的依赖注入了。
Spring的DI其实就是以反射作为最基础的技术手段。
一、反射机制实战
1.反射概念
指项目在运行状态下,可以知道任意一个类所有属性和方法,并且能够调用它的任意一个方法来获取信息,将这种动态调用对象方法的功能叫java语言的反射机制。
2.应用场景:
生成动态代理,面向切片编程。(ps:这两种是最常见的使用场景。而我写这篇文章的时候,遇到的不是这两种需求,而是需要知道某个方法的返回值。情况如下:正式环境的对接接口返回值解析错误,对接厂家的项目升级的时候,接口返回值进行了改动却没有进行通知,但是生产环境又不能debug,日志刚刚好没记录返回值,对接厂家又刚刚好非常忙没空理我,为了预防日后类似的场景,需要知道某个方法的返回值,这时我就想到了反射机制)
3.实例化
正常情况下我们用new方式实例化对象需要两步,(1)引入包名:import xx.xx.xx。(2)然后new 对象类名。
反射通过字符串实例化对象也是两步:(1)Class clazz = Class.forName("包名");相当于上面的第一步。(2)clazz.newInstance()
4.代码实战
@RequestMapping("agent")
public ModelAndView agent(HttpServletRequest request) throws Exception {
//返回值
Object obj = null;
ModelAndView mv = getAutoView();
try {
ISysUser user = ContextUtil.getCurrentUser();
if (user==null)
return getAutoView();
String un =user.getFullname();
//简单的权限判断,这判断可以根据实际情况来
ResultMessage resultMessage = new ResultMessage();
if(un.equals("超级管理员")) {
Class clazz = null;
String action = request.getParameter("action");
mv.addObject("action", action);
if (action==null || action.isEmpty())
return mv; Object object = null;
if (action.contains(".")) {
//获取对应包的class类
clazz = Class.forName(action);
//找到IOC容器中的实例化
object = AppUtil.getBean(clazz);
} else {
object = AppUtil.getBean(action);
}
String method = request.getParameter("method");
mv.addObject("method", method);
//参数类型
String param = request.getParameter("paramNum");
mv.addObject("paramNum", param);
//参数值
String reqBody = request.getParameter("reqBody");
mv.addObject("reqBody", reqBody);
if(!reqBody.isEmpty()) {
JSONArray jsonArray = JSONArray.fromObject(reqBody);
String[] params = param.split(";");
if (params.length == jsonArray.size()){
Object[] objects = new Object[params.length];
Class[] objMethods = new Class[params.length];
for (int i = 0; i < params.length; i++) {
if (param.startsWith("java.lang.")) {
Object objParam = jsonArray.get(i);
//基础类型判断
if (param.equals("java.lang.Integer")){
String str = String.valueOf(objParam);
Integer inv = Integer.parseInt(str);
objects[i] = inv;
} else if (param.equals("java.lang.Short")){
String str = String.valueOf(objParam);
Short inv = Short.parseShort(str);
objects[i] = inv;
} else if (param.equals("java.lang.Long")){
String str = String.valueOf(objParam);
Long inv = Long.parseLong(str);
objects[i] = inv;
} else if (param.equals("java.lang.Double")){
String str = String.valueOf(objParam);
Double inv = Double.parseDouble(str);
objects[i] = inv;
} else if (param.equals("java.lang.Float")){
String str = String.valueOf(objParam);
Float inv = Float.parseFloat(str);
objects[i] = inv;
} else if (param.equals("java.lang.Boolean")){
String str = String.valueOf(objParam);
Boolean inv = Boolean.parseBoolean(str);
objects[i] = inv;
} else {
objects[i] = objParam;
}
} else if (param.equals("java.util.Map")) {
Map map = jsonArray.getJSONObject(i);
objects[i] = map;
}else {
JSONObject jsonObject = jsonArray.getJSONObject(i);
Object cls = Class.forName(params[i]).newInstance();
Object objParam = JsonUtil.jsonTurnObject(jsonObject, cls);
objects[i] = objParam;
}
objMethods[i] = Class.forName(params[i]);
}
//获取想要执行的方法
Method md = object.getClass().getDeclaredMethod(method, objMethods);
obj = md.invoke(object, objects);//执行方法
System.out.println(obj);
} else
return getAutoView();
} else {
//获取想要执行的方法
Method md = object.getClass().getMethod(method);
obj = md.invoke(object);
System.out.println(obj);
} } else {
resultMessage.setMessage("你没有该权限!");
resultMessage.setResult(0);
}
} catch (Exception e) {
e.printStackTrace();
throw e;
}
if (obj!=null){
System.out.println(obj.getClass().toString());
switch (obj.getClass().toString()){
case "class java.lang.String":
break;
case "class java.lang.Long":
break;
case "class java.lang.Integer":
break;
case "class java.lang.Short":
break;
case "class java.lang.Byte":
break;
case "class java.lang.Float":
break;
case "class java.lang.Double":
break;
case "class java.lang.Boolean":
break;
case "class java.lang.Char":
break;
default:
obj = JSONArray.fromObject(obj);
break;
}
}
return mv.addObject("obj", obj);
}
该工具类就是将json转为相对应的类对象。
public static <T> T jsonTurnObject(JSONObject json, T clazz) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Field[] field = clazz.getClass().getDeclaredFields(); //获取实体类的所有属性,返回Field数组
for(int j=0 ; j<field.length ; j++){ //遍历所有属性
String name = field[j].getName(); //获取属性的名字
// System.out.println("attribute name:"+name);
Object object = json.get(name);//获取json属性
if (object != null) {
name = name.substring(0,1).toUpperCase()+name.substring(1); //将属性的首字符大写,方便构造get,set方法
Method fieldSetMet = clazz.getClass().getMethod("set"
+ name, field[j].getType()); String type = field[j].getGenericType().toString(); //获取属性的类型
if(type.equals("class java.lang.String")){ //如果type是类类型,则前面包含"class ",后面跟类名
fieldSetMet.invoke(clazz, object);
} else if (type.equals("class java.lang.Integer")){
String str = String.valueOf(object);
Integer inv = Integer.parseInt(str);
fieldSetMet.invoke(clazz, inv);
} else if (type.equals("class java.lang.Short")){
String str = String.valueOf(object);
Short inv = Short.parseShort(str);
fieldSetMet.invoke(clazz, inv);
} else if (type.equals("class java.lang.Long")){
String str = String.valueOf(object);
Long inv = Long.parseLong(str);
fieldSetMet.invoke(clazz, inv);
} else if (type.equals("class java.lang.Double")){
String str = String.valueOf(object);
Double inv = Double.parseDouble(str);
fieldSetMet.invoke(clazz, inv);
} else if (type.equals("class java.lang.Float")){
String str = String.valueOf(object);
Float inv = Float.parseFloat(str);
fieldSetMet.invoke(clazz, inv);
} else if (type.equals("class java.lang.Boolean")){
String str = String.valueOf(object);
Boolean inv = Boolean.parseBoolean(str);
fieldSetMet.invoke(clazz, inv);
}
}
} return clazz;
}
页面:
<form id="testWebserviceForm" method="post" action="agent.ht">
<table class="table table-striped table-hover table-bordered custom-table2" cellpadding="0" cellspacing="0" border="0" type="main">
<tr>
<th width="20%">包名: </th>
<td colspan="3"><input type="text" id="action" name="action" class="inputText" value="${action}"
validate="{required:false,maxlength:32}" placeholder="例:java.util.Map" /></td>
</tr>
<tr>
<th width="20%">方法名: </th>
<td colspan="3"><input type="text" id="method" name="method" class="inputText" value="${method}"
validate="{required:false,maxlength:255}" placeholder="例:put" /></td>
</tr>
<tr>
<th width="20%">参数类型: </th>
<td colspan="3"><input type="text" id="paramNum" name="paramNum" class="inputText" value="${paramNum}"
validate="{required:false,maxlength:255}" placeholder="例:java.lang.String(多个用;隔开)" /></td>
</tr>
<tr>
<th width="20%">参数: </th>
<td colspan="3">
<textarea id="reqBody" name="reqBody" class="inputText" rows="15" cols="50"
placeholder="例JSONArray:[{},{}]">${reqBody}</textarea>
</td>
</tr>
<tr>
<th width="20%">操作: </th>
<td colspan="3">
<button class="btn btn-xs btn-circle blue save" type="submit"><i
class="fa fa-sticky-note"></i>提交</button>
</td>
</tr>
</table>
</form>
附上运行结果
实战Java的反射机制的更多相关文章
- 浅谈Java的反射机制和作用
浅谈Java的反射机制和作用 作者:Java大师 欢迎转载,转载请注明出处 很多刚学Java反射的同学可能对反射技术一头雾水,为什么要学习反射,学习反射有什么作用,不用反射,通过new也能创建用户对象 ...
- Java 类反射机制分析
Java 类反射机制分析 一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.在计算机科学领域,反射是一类应用,它们能够自描述和自控制.这类应用通过某 ...
- java的反射机制
一.java的反射机制浅谈 最近研究java研究得很给力,主要以看博文为学习方式.以下是我对java的反射机制所产生的一些感悟,希望各位童鞋看到失误之处不吝指出.受到各位指教之处,如若让小生好好感动, ...
- Java中反射机制和Class.forName、实例对象.class(属性)、实例对象getClass()的区别
一.Java的反射机制 每个Java程序执行前都必须经过编译.加载.连接.和初始化这几个阶段,后三个阶段如下图: 其中
- java笔记--反射机制之基础总结与详解
一.反射之实例化Class类的5种方式: java的数据类型可以分为两类,即引用类型和原始类型(即基本数据类型). 对于每种类型的对象,java虚拟机会实例化不可变的java.lang.Class对象 ...
- JAVA的反射机制学习笔记(二)
上次写JAVA的反射机制学习笔记(一)的时候,还是7月22号,这些天就瞎忙活了.自己的步伐全然被打乱了~不能继续被动下去.得又一次找到自己的节奏. 4.获取类的Constructor 通过反射机制得到 ...
- java笔录---反射机制(1)
引言 为了方便记忆java的反射机制,在这里仔细的总结了一下.主要是怕以后忘记了,这样也方便回忆.因为最近利用空余时间深入的了解spring和Mybatis框架, 像spring中核心模块IO ...
- Java高新技术 反射机制
Java高新技术 反射机制 知识概要: (1)反射的基石 (2)反射 (3)Constructor类 (4)Field类 (5)Method类 (6)用反射方 ...
- java的反射机制浅谈(转)
原文链接:java的反射机制浅谈 一.java的反射机制浅谈 1.何谓反射机制 根据网文,java中的反射机制可以如此定义: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性 ...
随机推荐
- OpenCL编译环境配置(VS+Nvidia)
英伟达的显卡首先要下载安装CUDA开发包,可以参考这里的步骤: VS2015编译环境下CUDA安装配置 安装好CUDA之后,OpenCL的配置就已经完成了80%了,剩下的工作就是把OpenCL的路 ...
- 查看系统中安装了那些dotnet core 的SDK和运行时的命令
原文:查看系统中安装了那些dotnet core 的SDK和运行时的命令 1.查看SDK dotnet --list-sdks 2.查看运行时 dotnet --list-runtimes 效果如下图 ...
- 将grub写入mbr
现在习惯了开机启动的方法,所以我们把grub重新安装到硬盘的MBR上面. 这个步骤也有两种方法,一是安装grub4dos,然后启动,选中搜索硬盘上的linux引导文件,进入Linux之后再安装grub ...
- linux awk(good)
一个用awk处理字符串的例子: #!/bin/bash source="nokia201703148855" preffixStr=$(echo $source |awk '{pr ...
- Leetcode 100 Same Tree 二叉树
就是判断两棵树的值和结构是否相同 注意:要判断是否所有的树节点是否为NULL /** * Definition for a binary tree node. * struct TreeNode { ...
- 《Linux Device Drivers》第十一章 核心数据类型——note
基本介绍 因为Linux多平台特性,不管是哪一个重要驱动力应该是便携 与内核代码相关的核心问题应该是访问的同时是数据项的已知长度.能力和利用不同的处理器 内核使用的数据类型主要分为三类 类似int这种 ...
- 文章之间的基本总结Activity生命周期
子曰:溫故而知新,能够為師矣.<論語> 学习技术也一样,对于技术文档或者经典的技术书籍来说,指望看一遍就全然掌握,那基本不大可能,所以我们须要常常回过头再细致研读几遍,以领悟到作者的思想精 ...
- 如何将任意文件固定在 Win10 的开始屏幕中
虽然Wox和Launchy是我日常启动程序的主力方式,不过开始屏幕的图标方便归类,这是快速启动工具所不能提供的,因此我也会将最常用的程序在开始屏幕上分类固定. 最近需要将一个常用的批处理文件(*.ba ...
- WPF 自定义的图表(适用大量数据绘制)
原文:WPF 自定义的图表(适用大量数据绘制) 在WPF中绘制图表比较简单,有很多的第三方控件,但是在绘制大量数据的时候,就显得有些吃力,即便是自己用StreamGeometry画也达不到理想的效果, ...
- CCPlace,CCFlip*,CCToggleVisibility,CCMoveTo*,CCJumpTo*,CCScale*,CCRotate*,CCSkew*,fade,CCCardinalSp*
1 CCAction动作 CCAction作为一个基类.事实上质是一个接口(即抽象类),由它派生的实现类(如运动和转动等)才是我们实际使用的动作.CCAction 的绝大多数实现类都派生自CCF ...