源码位置:org.springframework.util.ReflectionUtils
该类会使用缓存等优化反射性能。
public static void main(String[] args) {
UserInfo userInfo = new UserInfo();
userInfo.setName("李白");
//找到Field对象(在缓存中获取对象)
Field field = ReflectionUtils.findField(UserInfo.class, "name");
ReflectionUtils.makeAccessible(field);
//通过反射获取对象
Object value = ReflectionUtils.getField(field, userInfo);
System.out.println(value);
}
1. doWithMethods类上所有方法回调
对给定类和超类的所有匹配方法执行给定的回调操作。
源码位置:
org.springframework.util.ReflectionUtils#doWithMethods(java.lang.Class<?>, org.springframework.util.ReflectionUtils.MethodCallback)
//对给定类和超类的所有匹配方法执行给定的回调操作。
//出现在子类和超类上的同一个命名方法将出现两次,除非被指定的{@linkmethodfilter}排除。
public static void doWithMethods(Class < ?>clazz, MethodCallback mc) {
doWithMethods(clazz, mc, null);
}
public static void doWithMethods(Class < ?>clazz, MethodCallback mc, @Nullable MethodFilter mf) {
//获取一个类上的所有方法
Method[] methods = getDeclaredMethods(clazz);
//遍历方法
for (Method method: methods) {
//若存在mf,且方法不匹配mf,跳过
if (mf != null && !mf.matches(method)) {
continue;
}
try {
//执行回调方法
mc.doWith(method);
} catch(IllegalAccessException ex) {
throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex);
}
}
//处理父类上的方法
if (clazz.getSuperclass() != null) {
doWithMethods(clazz.getSuperclass(), mc, mf);
}
//处理接口上的方法
else if (clazz.isInterface()) {
for (Class < ?>superIfc: clazz.getInterfaces()) {
doWithMethods(superIfc, mc, mf);
}
}
}
案例:
遍历failingMethod.getDeclaringClass()
所在的类及其超类的所有方法,来进行业务回调。
public class TestUtils {
public static void main(String[] args) throws NoSuchMethodException {
//方法所在的类
Method failingMethod = RetryService.class.getDeclaredMethod("fallback", int.class);
ReflectionUtils.doWithMethods(failingMethod.getDeclaringClass(),
new ReflectionUtils.MethodCallback() {
@Override
public void doWith(Method method) throws IllegalArgumentException,
IllegalAccessException {
//判断方法上是否存在某注解
Recover recover = AnnotationUtils.findAnnotation(method,
Recover.class);
//判断有@Recover的注解方法,方法的返回值是否和failingMethod一致
if (recover != null
&& method.getReturnType().isAssignableFrom(
failingMethod.getReturnType())) {
Class<?>[] parameterTypes = method.getParameterTypes();
//判断参数若是多个,且第一个参数为Throw类,那么打印
if (parameterTypes.length > 0
&& Throwable.class
.isAssignableFrom(parameterTypes[0])) {
System.out.println(method);
} else {
System.out.println(method);
}
}
}
});
}
}
工具类定义的MethodFilter类型
//判断是否是用户定义的方法
public static final MethodFilter USER_DECLARED_METHODS =
(method -> (!method.isBridge() && !method.isSynthetic() && method.getDeclaringClass() != Object.class));
//判断属性是否是复制的(非static、非final)
public static final FieldFilter COPYABLE_FIELDS =
field -> !(Modifier.isStatic(field.getModifiers()) || Modifier.isFinal(field.getModifiers()));
2. findMethod寻找Method对象
尝试使用提供的名称和参数类型在提供的类上查找Method。搜索直到Object的所有超类。
@Nullable
public static Method findMethod(Class < ?>clazz, String name) {
return findMethod(clazz, name, new Class < ?>[0]);
}
@Nullable
public static Method findMethod(Class < ?>clazz, String name, @Nullable Class < ?>...paramTypes) {
Assert.notNull(clazz, "Class must not be null");
Assert.notNull(name, "Method name must not be null");
Class < ?>searchType = clazz;
while (searchType != null) {
//利用缓存获取一个类的Mehod对象。
Method[] methods = (searchType.isInterface() ? searchType.getMethods() : getDeclaredMethods(searchType));
for (Method method: methods) {
//匹配到后返回
if (name.equals(method.getName()) && (paramTypes == null || Arrays.equals(paramTypes, method.getParameterTypes()))) {
return method;
}
}
//获取父类,继续循环
searchType = searchType.getSuperclass();
}
return null;
}
3. findField寻找Field对象
public static Field findField(Class < ?>clazz, @Nullable String name, @Nullable Class < ?>type) {
Assert.notNull(clazz, "Class must not be null");
Assert.isTrue(name != null || type != null, "Either name or type of the field must be specified");
Class < ?>searchType = clazz;
//当对象不为Object对象或者不为null,开始循环
while (Object.class != searchType && searchType != null) {
//借助缓存获取到Field对象
Field[] fields = getDeclaredFields(searchType);
for (Field field: fields) {
//若匹配到,直接返回
if ((name == null || name.equals(field.getName())) && (type == null || type.equals(field.getType()))) {
return field;
}
}
//获取父类对象
searchType = searchType.getSuperclass();
}
return null;
}
注意:获取到的Field,需要执行field.setAccessible(true);
。
public class Test {
public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException {
Field field = ReflectionUtils.findField(TestUtils.class, "name");
TestUtils testUtils = new TestUtils();
testUtils.setName("tom");
String name = (String) field.get(testUtils);
System.out.println(name);
}
}
抛出异常.png
网友评论