关于Java反射的一点代码
一、背景
最近又看了下java反射的一些东西,所以简单汇总记录一下.二、关于java反射2.1、什么是java反射
① 反射是一种动态获取信息及调用对象的一种机制。
② 对于一个在运行中的java类,我们都可以知道它的所有属性和方法。
③ 对于一个在运行状态中的对象,我们也都能通过反射来调用它的任意方法已经属性的调用及改变2.2、什么情况下会用到反射
① 一般来说我们在日常开发中直接用到反射的地方不多,它更多用于框架的开发
② 不能明确接口调用的是哪个函数,需要根据传入参数再运行时决定。
③ 不能明确传入函数的参数类型,但是又需要再运行时处理任意对象2.3、反射给我们提供了那些支持
① Class.forName(String className): 返回给定字符串名称的类或接口的相关类对象
② getDeclaredConstructors():返回一个数组,包含类的公共构造函数
③ getConstructor(Class<?>, paremeterTypes):返回指定反射类的指定入参类型的构造函数
④ getDeclaredMethos():返回一个数组,包含反射类的所有公共、保护、私有、默认方法(不包括继承的方法 )
⑤ getDeclaredFields():返回一个数组,包含反射类的所有字段属性
⑥ getDeclaredField(String fieldName): 返回反射类指定名称的字段属性
⑦ getMethods(): 返回一个数组,包含反射类的公共方法,包含继承的方法
⑧ getMethod(String name, Class<?>, paremeteraTypes): 返回反射类指定的公共成员方法
PS:更多信息,请参考官方文档。 三、代码示例 @Data public class Person { private String name; private int age; public Person(){ System.out.println("我是默认构造方法,我被调用了!"); } public Person(String name, int age){ System.out.println("有参构造 --- 姓名为:" + name + " 年龄为:" + age); } }
import com.example.easyexcel.model.Person; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; public class Test { public static void main(String args[]) throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, NoSuchFieldException { System.out.println("通过反射调用类的默认构造方法"); Class person = Class.forName("com.example.easyexcel.model.Person"); Constructor constructor = person.getConstructor(null); constructor.newInstance(null); System.out.println("通过反射调用类的有参构造方法"); Constructor constructor1 = person.getConstructor(String.class, int.class); constructor1.newInstance("XiaoMing", 19); System.out.println("======================================"); Person bean = new Person(); bean.setName("ZZSS"); Field[] fields = bean.getClass().getDeclaredFields(); Field field = bean.getClass().getDeclaredField("name"); field.setAccessible(true); Object objectName = field.get(bean); System.out.println("获取指定字段name的值为:" + objectName); System.out.println("======================================"); for(int i = 0;i < fields.length;i++){ Field fieldTmp = fields[i]; // 设置属性是可以访问的 fieldTmp.setAccessible(true); // 得到此属性的值 Object valTmp = fieldTmp.get(bean); String type = fieldTmp.getType().toString(); System.out.println("字段类型为:" + type); System.out.println("属性名:" + fieldTmp.getName()); System.out.println("属性值:" + valTmp); System.out.println("======================================"); // 得到此属性的类型 if(type.endsWith("String")) { // 给属性设值 fieldTmp.set(bean,"LFG"); } else if(type.endsWith("int") || type.endsWith("Integer")) { // 给属性设值 fieldTmp.set(bean,121); } } System.out.println("重新设值后的对象属性为:"+bean.getName()+" "+bean.getAge()); } }
Java
程序输出如下:
通过反射调用类的默认构造方法
我是默认构造方法,我被调用了!
通过反射调用类的有参构造方法
有参构造 --- 姓名为:XiaoMing 年龄为:19
======================================
我是默认构造方法,我被调用了!
获取指定字段name的值为:ZZSS
======================================
字段类型为:class java.lang.String
属性名:name
属性值:ZZSS
======================================
字段类型为:int
属性名:age
属性值:0
======================================
重新设值后的对象属性为:LFG 121
四、日志模块中部分代码示例 private void saveSysLog(ProceedingJoinPoint joinPoint, long time) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); SysLogEntity sysLog = new SysLogEntity(); SysLog syslog = method.getAnnotation(SysLog.class); if (syslog != null) { // 注解上的描述 sysLog.setOperation(syslog.value()); } // 请求的方法名 String className = joinPoint.getTarget().getClass().getName(); String methodName = signature.getName(); sysLog.setMethod(className + "." + methodName + "()"); // 请求的参数 Object[] args = joinPoint.getArgs(); try { String params = new Gson().toJson(args[0]); sysLog.setParams(params); … } catch (Exception e) { } // 获取request HttpServletRequest request = HttpContextUtils.getHttpServletRequest(); // 设置IP地址 sysLog.setIp(IPUtils.getIpAddr(request)); … sysLogApi.saveLog(sysLog); }
Java
PS: 可以参见:Springboot自定义注解日志管理实现