一、介绍
1、简介
org.springframework.util.ReflectionUtils
是 Spring 框架提供的一个反射工具类,它封装了 Java 反射 API 的一些常用操作,使得我们能够更加方便、简洁地使用反射功能。
虽然 ReflectionUtils
提供了很多便捷的方法,但使用反射仍然需要谨慎。反射操作可能会破坏封装性、增加性能开销,并可能引发安全问题。因此,在不需要动态访问的情况下,最好避免使用反射。
二、API
1、获取 Class 对象
ReflectionUtils
提供了多种获取 Class
对象的方法,如:
(1)findClass(String name): 根据类名获取 Class 对象,与 Class.forName(String) 类似,但会缓存已经加载过的类。
(2)getClass(Object obj): 获取对象的运行时类,与 obj.getClass() 等效。
(3)getUserClass(Object obj): 如果对象是代理对象,则获取其背后的实际类(即目标类),否则与 getClass(Object) 相同。
2、访问字段(Field)
(1)findField(Class<?> clazz, String name): 在给定的类及其父类中查找具有指定名称的字段。
import org.springframework.util.ReflectionUtils;
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
// 省略其他方法...
}
public class ReflectionExample {
public static void main(String[] args) {
Person person = new Person("zs");
String fieldName = "name";
// 使用 ReflectionUtils 获取私有字段的值
String nameValue = (String) ReflectionUtils.getFieldValue(person, fieldName);
System.out.println("Name value: " + nameValue); // 输出: Name value: zs
}
}
(2)findField(Class<?> clazz, String name, Class<?> type): 根据名称和类型查找字段。
(3)getField(Field field): 获取可访问的字段对象,如果字段是私有的,会设置其为可访问。
(4)setField(Object obj, String name, Object value): 设置指定对象的字段值。
public class ReflectionExample {
public static void main(String[] args) {
Person person = new Person("John Doe");
String fieldName = "name";
String newValue = "zs";
// 使用 ReflectionUtils 设置私有字段的值
ReflectionUtils.setField(person, fieldName, newValue);
// 再次获取并验证字段值已更改
String updatedValue = (String) ReflectionUtils.getFieldValue(person, fieldName);
System.out.println("Updated name value: " + updatedValue); // 输出: Updated name value: zs
}
}
(5)getFieldValue(Object obj, String name): 获取指定对象的字段值。
3、调用方法(Method)
(1)findMethod(Class<?> clazz, String name, Class<?>... paramTypes):
查找具有指定名称和参数类型的方法。
Method method = ReflectionUtils.findMethod(aClass, methodName);
(2)invokeMethod(Method method, Object target): 调用无参数方法。
Object[] parameters = new Object[parameterTypes.length];
result = ReflectionUtils.invokeMethod(preCheckMethod, null, parameters);
(3)invokeMethod(Method method, Object target, Object... args): 调用带参数的方法。
(4)invokeJdbcMethod(Method method, Object target, Object... args):
专为 JDBC 方法设计的调用,处理 SQL 异常。
(5)makeAccessible(Method method): 确保方法可以访问,即使它是私有的。
4、构造函数和实例化
(1)getConstructorIfAvailable(Class<?> clazz, Class<?>... paramTypes):
尝试获取指定参数类型的构造函数,如果找不到则返回 null。
(2)instantiateClass(Constructor<?> ctor, Object... args): 使用指定的构造函数和参数实例化类。
(3)newInstance(Class<?> clazz, Object... args): 简化版的实例化方法,它内部会查找合适的构造函数并调用 instantiateClass。
5、其他实用方法
(1)isAssignable(Class<?> lhsType, Class<?> rhsType): 判断一个类是否可以赋值给另一个类(考虑继承关系)。
(2)doesMethodDeclareException(Method method, Class<?> exceptionType):
检查方法是否声明了指定类型的异常。
import org.springframework.util.ReflectionUtils;
import java.io.IOException;
public class ExampleWithException {
public void methodThatThrows() throws IOException {
// ... 方法实现 ...
}
}
public class ReflectionExample {
public static void main(String[] args) {
boolean declaresException = ReflectionUtils.doesMethodDeclareException(
ReflectionUtils.findMethod(ExampleWithException.class, "methodThatThrows"), IOException.class);
System.out.println("Declares IOException: " + declaresException); // 输出: Declares IOException: true
}
}
(3)getUniqueDeclaredMethods(Class<?> leafClass): 获取类中声明的所有方法,包括继承的方法,但排除重写的方法,确保每个方法只出现一次。
(4)getAllDeclaredMethods(Class<?> leafClass): 获取类中声明的所有方法,包括继承的方法,但不排除重写的方法。
(5)getDeclaredMethods(Class<?> clazz): 获取类中直接声明的所有方法,不包括继承的方法。
(6)getDeclaredFields(Class<?> clazz): 获取类中直接声明的所有字段。
Method method = ReflectionUtils.findMethod(aClass, methodName);