第14篇:Mybatis中反射工具
Mybatis
!!! tip 我们知道在java中基于反射的速度相对来说是很慢的, 但是如果对反射信息加了缓存性能可以提升1半以上, 如果在对反射设置了忽略安全检查, 性能更是会再提升1半。那么这个时候 反射带来的性能问题基本可以忽略了。在Mybatis中关于反射的工具就可以很大程度来解决这个问题。本篇讲解下Mybatis中的工具类, 以后在项目中也可以直接使用。 !!!
一、反射缓存类 Reflector
所有的反射对象都会被生成一个 Reflector, Reflector 会把反射的方法、构造、字段、类型等信息都缓存起来。这样的设计主要是为了解决性能问题。
java
1public class Reflector {
2
3 private final Class<?> type;
4 private final String[] readablePropertyNames;
5 private final String[] writablePropertyNames;
6 private final Map<String, Invoker> setMethods = new HashMap<>();
7 private final Map<String, Invoker> getMethods = new HashMap<>();
8 private final Map<String, Class<?>> setTypes = new HashMap<>();
9 private final Map<String, Class<?>> getTypes = new HashMap<>();
10 private Constructor<?> defaultConstructor;
11
12 private Map<String, String> caseInsensitivePropertyMap = new HashMap<>();
13
14}ReflectorFactory 反射工厂用来缓存反射对象 Reflector
java
1
2public class DefaultReflectorFactory implements ReflectorFactory {
3 private boolean classCacheEnabled = true;
4 private final ConcurrentMap<Class<?>, Reflector> reflectorMap = new ConcurrentHashMap<>();
5
6 @Override
7 public Reflector findForClass(Class<?> type) {
8 if (classCacheEnabled) {
9 // synchronized (type) removed see issue #461
10 return MapUtil.computeIfAbsent(reflectorMap, type, Reflector::new);
11 } else {
12 return new Reflector(type);
13 }
14 }
15
16}二、通过反射操作对象 MetaObject
MetaObject 从名字来看就是对对象进行操作,他的操作都是通过反射来进行的。
2.1 简单对象操作
java
1 @AllArgsConstructor
2 @ToString
3 public static class Person {
4
5 @Getter(AccessLevel.PRIVATE)
6 @Setter(AccessLevel.PRIVATE)
7 private String name;
8
9 @Getter(AccessLevel.PRIVATE)
10 @Setter(AccessLevel.PRIVATE)
11 private int age;
12
13 @Getter(AccessLevel.PRIVATE)
14 @Setter(AccessLevel.PRIVATE)
15 private Long userId;
16 }
17
18 /**
19 * 通过反射给对象赋值
20 */
21 @Test
22 public void metaObjectTest() {
23 Person jay = new Person("周杰伦", 40, 1L);
24 MetaObject jayMetaObject = MetaObject.forObject(jay, new DefaultObjectFactory(), new DefaultObjectWrapperFactory(), new DefaultReflectorFactory());
25 if (jayMetaObject.hasGetter("name")) {
26 Class<?> name = jayMetaObject.getGetterType("name");
27 // class java.lang.String
28 System.out.println(name);
29 jayMetaObject.setValue("name", "昆凌");
30 // 昆凌
31 System.out.println(jayMetaObject.getValue("name"));
32 }
33 // 昆凌
34 System.out.println(jay.getName());
35 }2.2 嵌套对象操作
java
1 @AllArgsConstructor
2 @ToString
3 public static class Person {
4
5 @Getter(AccessLevel.PRIVATE)
6 @Setter(AccessLevel.PRIVATE)
7 private String name;
8
9 @Getter(AccessLevel.PRIVATE)
10 @Setter(AccessLevel.PRIVATE)
11 private int age;
12
13 @Getter(AccessLevel.PRIVATE)
14 @Setter(AccessLevel.PRIVATE)
15 private Long userId;
16 }
17
18 @AllArgsConstructor
19 @ToString
20 public static class School {
21
22 @Getter(AccessLevel.PRIVATE)
23 @Setter(AccessLevel.PRIVATE)
24 private String name;
25
26 @Getter(AccessLevel.PRIVATE)
27 @Setter(AccessLevel.PRIVATE)
28 private Person person;
29 }
30
31 @Test
32 public void fillChildObjectTest() {
33 School school = new School("西天大学", new Person("周杰伦", 40, 1L));
34 MetaObject schoolMetaObject = MetaObject.forObject(school, new DefaultObjectFactory(), new DefaultObjectWrapperFactory(), new DefaultReflectorFactory());
35 // 周杰伦
36 System.out.println(schoolMetaObject.getValue("person.name"));
37 schoolMetaObject.setValue("person.name", "昆凌");
38 // 昆凌
39 System.out.println(school.getPerson().getName());
40 }三、获取反射信息 MetaClass
MetaClass 主要是对 Reflector信息的一个包装并提供些更高级的操作。如跟嵌套类赋值
java
1 @Test
2 public void metaClassTest() throws Exception {
3 MetaClass metaClass = MetaClass.forClass(School.class, new DefaultReflectorFactory());
4 // class com.test.tool.MetaObjectTest$Person
5 System.out.println(metaClass.getGetterType("person"));
6
7 School school = new School();
8 Invoker setNameInvoker = metaClass.getSetInvoker("name");
9 // 通过反射给空对象赋值
10 setNameInvoker.invoke(school, new Object[]{"Jay"});
11
12 // 通过反射获取空对象
13 Invoker getNameInvoker = metaClass.getGetInvoker("name");
14 // Jay
15 System.out.println(getNameInvoker.invoke(school, new Object[]{}));
16 }