前言
ReflectionUtils应该是Springboot内置工具类梳理的最后一篇了,可能很多人都没有听说过这个工具类,这个类封装的是一些与java反射相关的静态工具方法。可能很多人也知道反射,却不怎么经常使用反射。其实反射是一个很有用的技术点,我认为是可以和AOP比肩的,甚至有过之而不及。大家都知道AOP是面向切面编程,可以在定义的切面前、后执行一些操作,但是反射更厉害,它可以在程序运行时,对已装载的任意类的属性和方法进行操作,这就是java的反射机制。
ReflectionUtils
org.springframework.util.ReflectionUtils中包含的静态方法其实有很多,主要分为两类:对类中属性的操作和对类中方法的操作。
对属性的操作
获取属性字段
Field findField(Class clazz, String name),在类中查找指定属性。
-
@Test
-
public
void
test1(
){
-
//查找属性字段realName
-
Field realName =
ReflectionUtils.
findField(
Employee.
class,
"realName");
-
Assert.
notNull(realName,
"获取员工类的姓名属性失败");
-
}
Field findField(Class clazz, String name, Class type),更精确的在类中查找指定属性,可以在指定属性的类型。
-
@Test
-
public
void
test2(
){
-
//查找属性字段realName,类型是String
-
Field realName =
ReflectionUtils.
findField(
Employee.
class,
"realName",
String.
class);
-
Assert.
notNull(realName,
"获取员工类的姓名属性失败");
-
}
设置属性字段的值
Object getField(Field field, Object target),获取 target 对象的 field 属性值。
-
@Test
-
public
void
test3
() {
-
//声名一个对象,姓名是zhangsan
-
Employee
zhangsan
=
new
Employee(
"zhangsan");
-
//获取Employee类中的realName属性字段
-
Field
field
= ReflectionUtils.findField(Employee.class,
"realName");
-
//取消realName属性的private权限控制
-
ReflectionUtils.makeAccessible(field);
-
//获取员工对象的姓名字段的值
-
Object
value
= ReflectionUtils.getField(field, zhangsan);
-
Assert.isTrue(value.equals(
"zhangsan"),
"员工zhangsan的姓名字段取值失败" );
-
}
void setField(Field field, Object target, Object value),可以设置 target 对象的 field 属性值,值为 value。
-
@Test
-
public
void
test4
() {
-
Employee
zhangsan
=
new
Employee(
"zhangsan");
-
//获取Employee类中的realName属性字段
-
Field
field
= ReflectionUtils.findField(Employee.class,
"realName");
-
//取消realName属性的private权限控制
-
ReflectionUtils.makeAccessible(field);
-
//把员工对象zhangsan的姓名字段值设置为zhangsan_v2
-
ReflectionUtils.setField(field, zhangsan,
"zhangsan_v2");
-
Object
value
= ReflectionUtils.getField(field, zhangsan);
-
Assert.isTrue(value.equals(
"zhangsan_v2"),
"员工zhangsan的姓名字段取值失败" );
-
}
void shallowCopyFieldState(Object src, Object dest),如果两个对象是同一个类的实现,且希望把一对象的值复制到另外一个对象上,可以使用这个方法,src是源对象,dest是目标对象。
-
@Test
-
public
void
test5
() {
-
Employee
zhangsan
=
new
Employee(
"zhangsan");
-
Employee
tmp
=
new
Employee();
-
//把对象zhangsan的值复制到对象tmp上,这里要注意,复制的对象类型要相同
-
ReflectionUtils.shallowCopyFieldState(zhangsan, tmp);
-
Assert.isTrue(tmp.getRealName().equals(
"zhangsan"),
"对象的属性复制失败了" );
-
}
void makeAccessible(Field field),取消java的权限控制检查,方便private私有访问权限的操作。
-
@Test
-
public
void
test4(
) {
-
Employee zhangsan =
new
Employee(
"zhangsan");
-
//取消realName属性的private权限控制
-
ReflectionUtils.
makeAccessible(field);
-
}
void doWithFields(Class clazz, ReflectionUtils.FieldCallback fc),可以对类的每个属性执行 回调方法,简单的理解就是可以定义一个回调方法,在对类的属性操作完后,回调方法内的逻辑就会被执行。另外还有两个方法,功能也很类似:void doWithFields(Class clazz, ReflectionUtils.FieldCallback fc,ReflectionUtils.FieldFilter ff),不仅有回调方法,还可以增加过滤的逻辑;void doWithLocalFields(Class clazz, ReflectionUtils.FieldCallback fc),只对本类的属性可以执行回调方法,不包括父类的。举个例子,简单的理解一下,实在理解不了就放弃吧,因为我也觉得这个确实有点鸡肋。假如员的性别在程序中是以1和0进行区分,对外展示的时候要转换为“男”和“女”:
-
public
class
SexFieldCallBack<
T>
implements
ReflectionUtils.FieldCallback{
-
private Object obj;
-
private Integer sexFlag=
-1;
-
public SexFieldCallBack(Object obj) {
-
this.obj = obj;
-
}
-
@Override
-
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
-
field.setAccessible(
true);
-
if (field.getName().
equals(
"sexFlag")) {
-
Object
value = field.
get(obj);
-
this.sexFlag= ((Integer)
value);
-
}
-
if(field.getName().
equals(
"sex")){
-
if (
1==
this.sexFlag) {
-
field.
set(obj,
"男");
-
}
-
if (
0==
this.sexFlag) {
-
field.
set(obj,
"女");
-
}
-
}
-
}
-
}
-
@Test
-
public void test6() throws IllegalAccessException, InstantiationException {
-
Employee employee = Employee.
class.newInstance();
-
employee.setRealName(
"zhangsan");
-
//性别标志位,1:男,0:女
-
employee.setSexFlag(
1);
-
ReflectionUtils.doWithFields(Employee.
class,
new SexFieldCallBack(employee) );
-
Assert.isTrue(
"男".
equals(employee.getSex()),
"性别转换失败了");
-
}
对方法的操作
-
@Data
-
public
class
Employee
implements
Serializable {
-
private
String realName;
-
public
void
hello(
String name) {
-
System.
out.
println(name +
",你好!我是" +
this.
realName);
-
}
-
public
void
say(
String name) {
-
System.
out.
println(name +
",你好!我是" +
this.
realName);
-
}
-
public
String
hello(
String name, Boolean isReturn) {
-
String msg = name +
",你好!我是" +
this.
realName;
-
if (isReturn) {
-
System.
out.
println(msg);
-
return msg;
-
}
-
return
null;
-
}
-
}
获取方法
Method findMethod(Class clazz, String name),在类中查找指定名字方法
-
@Test
-
public
void
test7
()
throws IllegalAccessException, InstantiationException, InvocationTargetException {
-
//查找类中的hello方法
-
//这里要注意如果类中有方法名相同的重载方法时,一要要用下面的方法,把参数的类型给带上
-
//如果不是重载方法,用这个也没问题
-
Method
say
= ReflectionUtils.findMethod(Employee.class,
"say");
-
Employee
employee
= Employee.class.newInstance();
-
employee.setRealName(
"zhangsan");
-
say.invoke(employee,
"lisi");
-
}
Method findMethod(Class clazz, String name, Class... paramTypes),有的时候同一个类可能会有多个方法名相同,形参数不同的重载方法,可以使用这个方法更精确的在类中找到指定方法;
-
@Test
-
public void test8() throws IllegalAccessException, InstantiationException, InvocationTargetException {
-
Method hello = ReflectionUtils.findMethod(Employee.
class,
"hello",String.
class,Boolean.
class);
-
Employee employee = Employee.
class.newInstance();
-
employee.setRealName(
"zhangsan");
-
//执行employee对象的hello方法
-
Object msg = hello.invoke(employee,
"lisi",
true);
-
System.
out.println(msg);
-
}
Method[] getAllDeclaredMethods(Class leafClass),获得类中所有方法,包括继承而来的。
-
@Test
-
public void test9() {
-
//获取类中所有的方法,包括继承而来的
-
Method[] methods = ReflectionUtils.getAllDeclaredMethods(Employee.
class);
-
for (Method o : methods) {
-
System.
out.println(o.getName());
-
}
-
}
执行方法
Object invokeMethod(Method method, Object target),执行无参数的方法;
Object invokeMethod(Method method, Object target, Object... args),执行有参数的方法
void makeAccessible(Method method),如果是私有方法,可以取消 Java 权限检查,以便后续执行该私有方法
-
@Test
-
public void test10() throws IllegalAccessException, InstantiationException, InvocationTargetException {
-
//获取set方法
-
Method setRealName = ReflectionUtils.findMethod(Employee.
class,
"setRealName", String.
class);
-
//反射实例化一个对象
-
Employee employee = Employee.
class.newInstance();
-
//放开权限检查
-
ReflectionUtils.makeAccessible(setRealName);
-
//执行set方法
-
setRealName.invoke(employee,
"zhangsan");
-
//获取get方法
-
Method getRealName = ReflectionUtils.findMethod(Employee.
class,
"getRealName");
-
//执行get方法
-
Object result = getRealName.invoke(employee);
-
Assert.isTrue(result.
equals(
"zhangsan"),
"getRealName方法执行失败");
-
}
转载:https://blog.csdn.net/fox9916/article/details/128346911