JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
如下获取对应的方法执行结果,method为需要执行的方法,可写在一个枚举中动态获取
Method method = UserService.getClass().getMethod("method",User.class);
result = (List<String>)method.invoke(UserService, args);
JAVA反射的方法主要有三种:Class,Method,Field。
Field获取对象的属性
获取Field的常用方法:
getFields():获取public类型的属性(也可以获取到父类的public修饰的属性)并返回一个Field数组;
getDeclaredFields(): 获取所有属性(包括public、protected、default、private权限类型,但不能获取继承父类的属性)并返回一个Field数组;
getField(String name):获取特定的public对象属性,name为属性名;
getDeclaredField(String name): 获取特定的对象属性,属性的访问权限可以是public、protected、default、private,name为属性名;
例如:
User user = new User(); user.setName("zhangsan"); // getDeclaredField可以获取私有属性 Field field = User.class.getDeclaredField("name"); // 设置该属性可以被访问(如果没有这步,你拿到了Field对象但是不能拿到值) field.setAccessible(true); // 将对象传入,这里很多人会有误区,为什么要传对象,不传对象不能拿到值吗? // 答:不传拿不到值,因为,Class对象是单例(属于类的),你不指定对象,则拿不到值 String name = (String) field.get(user);
(2)Field对象的常用方法:
getType():返回Field对象的类型
getName():返回Field对象的名字
set(Object obj,Object value):设置对象属性的值,obj为实例对象,value为要为属性设置的新值
2.Method
获取对象方法,执行对象方法
继承的方法(包括重载、重写和隐藏的)会被编译器强制执行,这些方法都无法反射。
(1)获取Method对象的方法
getMethod(String name,Object type):获取特定的public对象方法,name为方法名,type为参数类型;
getDeclaredMethod(String name,Object type): 获取特定的对象方法,属性的访问权限可以是public、protected、default、private,name为方法名,type为参数类型;
(2)Method对象的常用方法:
getReturntype():获取Method对象返回类型
getName():返回Method对象的名字
invoke(Object obj,Object value):执行对象方法,obj为实例对象,value为方法参数,没有参数写null
Spring中ReflectionUtils常用方法详解
Spring针对反射提供的工具类:ReflectionUtils。反射在容器中使用是非常频繁的了,ReflectionUtils中也提供了想当多的有用的方法,一起来看看。
在ReflectionUtils中提供了一些专门用于处理在反射中异常相关的方法,这些方法一般在Spring框架内部使用,当然,出于规范考虑,我们在开发中涉及到反射的异常,也可以使用这些方法。
调用method方法:invokeMethod(Method method, Object target)
//遍历所有方法
doWithMethods(Class targetClass, MethodCallback mc)
获取类的所有的方法的:getAllDeclaredMethods(Class leafClass)
用于对象的拷贝的方法(类必须是同一类或子类):shallowCopyFieldState(final Object src, final Object dest)
找到所有的bean中TestClass.class注解
Map<String ,Object> beans = getApplicationContext().getBeansWithAnnotation(TestClass.class);
for(Object bean : beans.values()) {
logger.info("测试类{}", bean.getClass().getName());
//遍历bean的所有method,m为里面的Method,m.isAnnotationPresent为判断method上面是否有TestMethod注解做为条件
ReflectionUtils.doWithMethods(bean.getClass(), m->testMethod(bean, m), m->m.isAnnotationPresent(TestMethod.class));
}
*Method findMethod(Class<?> clazz, String name, Class<?>... paramTypes) *
在类型clazz上,查询name方法,参数类型列表为paramTypes;
查找属性Field findField(Class<?> clazz, String name)
查找所有属性:Field[] fields = getDeclaredFields(searchType);
//在method,class,Field上面查找的一个SpanCustomizer注解 找method上面的一个SpanCustomizer注解 AnnotatedElementUtils.findMergedAnnotation(method, SpanCustomizer.class);
找Field上面的一个SpanCustomizer注解
AnnotatedElementUtils.findMergedAnnotation(field, SpanCustomizer.class);
找User类上面的一个SpanCustomizer注解
AnnotatedElementUtils.findMergedAnnotation(user.class, SpanCustomizer.class);