Reflector类负责对一个类进行反射解析,并将解析后的结果在属性中存储起来。
一个类反射解析后都有哪些属性呢?我们可以通过Reflector类定义的属性来查看
public class Reflector {// 要被反射解析的类private final Class<?> type;// 可读属性列表即有get方法的属性列表private final String[] readablePropertyNames;// 可写属性列表即有set方法的属性列表private final String[] writeablePropertyNames;// set方法映射表。键为属性名,值为对应的set方法private final Map<String, Invoker> setMethods = new HashMap<String, Invoker>();// get方法映射表。键为属性名,值为对应的get方法private final Map<String, Invoker> getMethods = new HashMap<String, Invoker>();// set方法输入参数类型映射表。键为属性名,值为对应set方法输入参数类型的Classprivate final Map<String, Class<?>> setTypes = new HashMap<String, Class<?>>();// get方法返回值类型映射表。键为属性名,值为对应get方法返回值类型的Classprivate final Map<String, Class<?>> getTypes = new HashMap<String, Class<?>>();// 默认构造器private Constructor<?> defaultConstructor;// 忽略大小写的属性映射表。键为属性名全大写值,值为属性名private Map<String, String> caseInsensitivePropertyMap = new HashMap<String, String>();// Reflector类反射解析一个类的过程是由构造函数触发的public Reflector(Class<?> clazz) {// 记录被反射解析的类type = clazz;// 解析默认造方法addDefaultConstructor(clazz);// 解析所有的getteraddGetMethods(clazz);// 解析所有的setteraddSetMethods(clazz);// 解析所有属性addFields(clazz);// 获取可读属性列表readablePropertyNames = getMethods.keySet().toArray(new String[getMethods.keySet().size()]);// 获取可写属性列表writeablePropertyNames = setMethods.keySet().toArray(new String[setMethods.keySet().size()]);// 获取忽略大小写的属性列表for (String propName : readablePropertyNames) {caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);}for (String propName : writeablePropertyNames) {caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);}}.....
}
创建方式:
1、直接new
Reflector reflector = new Reflector(User.class);
2、工厂创建
ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
Reflector reflector = reflectorFactory.findForClass(User.class);
对外暴露的方法:
Reflector reflector = new Reflector(User.class);
// 获取被解析反射的类
Class<?> type = reflector.getType();
// 根据属性名获取对应的set方法
Invoker setInvoker = reflector.getSetInvoker("name");
// 根据属性名获取对应的get方法
Invoker getInvoker = reflector.getGetInvoker("name");
// 获取所有可读属性列表
String[] getablePropertyNames = reflector.getGetablePropertyNames();
// 获取所有可写属性列表
String[] setablePropertyNames = reflector.getSetablePropertyNames();
// 获取默认构造器
Constructor<?> defaultConstructor = reflector.getDefaultConstructor();
// 根据属性名获取对应get方法返回值类型
Class<?> getterType = reflector.getGetterType("name");
// 根据属性名获取对应set方法参数类型
Class<?> setterType = reflector.getSetterType("name");
// 根据属性名不区分大小写获取属性名
String name = reflector.findPropertyName("name");
// 判断属性是否存在getter方法
boolean hasGetter = reflector.hasGetter("name");
// 判断属性是否存在getter方法
boolean hasSetter = reflector.hasSetter("name");
测试案例:
@Testpublic void test1()throws Exception{Reflector reflector = new Reflector(User.class);Class<?> type = reflector.getType();System.out.println("要被反射解析的类:"+type);Constructor<?> defaultConstructor = reflector.getDefaultConstructor();System.out.println(defaultConstructor);String[] getablePropertyNames = reflector.getGetablePropertyNames();for (String propertyName : getablePropertyNames) {System.out.println("可读属性:"+propertyName);}System.out.println("----------------------------------------------------------");String[] setablePropertyNames = reflector.getSetablePropertyNames();for (String propertyName : setablePropertyNames) {System.out.println("可写属性:"+propertyName);}System.out.println("--------------------------------------------------");for (String propertyName : reflector.getGetablePropertyNames()) {Invoker name = reflector.getGetInvoker(propertyName);Object invoke = name.invoke(new User(), null);System.out.println("执行属性"+propertyName+"的get方法:"+invoke);}}
测试结果:
该类里面还有一个值的注意的小工具类可以直接拿来使用,生成方法签名
private String getSignature(Method method) {StringBuilder sb = new StringBuilder();Class<?> returnType = method.getReturnType();if (returnType != null) {sb.append(returnType.getName()).append('#');}sb.append(method.getName());Class<?>[] parameters = method.getParameterTypes();for (int i = 0; i < parameters.length; i++) {if (i == 0) {sb.append(':');} else {sb.append(',');}sb.append(parameters[i].getName());}return sb.toString();}