第14篇:Mybatis中反射工具

西魏陶渊明 ... 2022-4-26 Mybatis 大约 2 分钟

提示

我们知道在java中基于反射的速度相对来说是很慢的, 但是如果对反射信息加了缓存性能可以提升1半以上, 如果在对反射设置了忽略安全检查, 性能更是会再提升1半。那么这个时候 反射带来的性能问题基本可以忽略了。在Mybatis中关于反射的工具就可以很大程度来解决这个问题。本篇讲解下Mybatis中的工具类, 以后在项目中也可以直接使用。

# 一、反射缓存类 Reflector

所有的反射对象都会被生成一个 Reflector, Reflector 会把反射的方法、构造、字段、类型等信息都缓存起来。这样的设计主要是为了解决性能问题。

public class Reflector {

  private final Class<?> type;
  private final String[] readablePropertyNames;
  private final String[] writablePropertyNames;
  private final Map<String, Invoker> setMethods = new HashMap<>();
  private final Map<String, Invoker> getMethods = new HashMap<>();
  private final Map<String, Class<?>> setTypes = new HashMap<>();
  private final Map<String, Class<?>> getTypes = new HashMap<>();
  private Constructor<?> defaultConstructor;

  private Map<String, String> caseInsensitivePropertyMap = new HashMap<>();
  
}  
1
2
3
4
5
6
7
8
9
10
11
12
13
14

ReflectorFactory 反射工厂用来缓存反射对象 Reflector


public class DefaultReflectorFactory implements ReflectorFactory {
  private boolean classCacheEnabled = true;
  private final ConcurrentMap<Class<?>, Reflector> reflectorMap = new ConcurrentHashMap<>();
  
  @Override
  public Reflector findForClass(Class<?> type) {
    if (classCacheEnabled) {
      // synchronized (type) removed see issue #461
      return MapUtil.computeIfAbsent(reflectorMap, type, Reflector::new);
    } else {
      return new Reflector(type);
    }
  }
  
}  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 二、通过反射操作对象 MetaObject

MetaObject 从名字来看就是对对象进行操作,他的操作都是通过反射来进行的。

# 2.1 简单对象操作

    @AllArgsConstructor
    @ToString
    public static class Person {

        @Getter(AccessLevel.PRIVATE)
        @Setter(AccessLevel.PRIVATE)
        private String name;

        @Getter(AccessLevel.PRIVATE)
        @Setter(AccessLevel.PRIVATE)
        private int age;

        @Getter(AccessLevel.PRIVATE)
        @Setter(AccessLevel.PRIVATE)
        private Long userId;
    }

    /**
     * 通过反射给对象赋值
     */
    @Test
    public void metaObjectTest() {
        Person jay = new Person("周杰伦", 40, 1L);
        MetaObject jayMetaObject = MetaObject.forObject(jay, new DefaultObjectFactory(), new DefaultObjectWrapperFactory(), new DefaultReflectorFactory());
        if (jayMetaObject.hasGetter("name")) {
            Class<?> name = jayMetaObject.getGetterType("name");
            // class java.lang.String
            System.out.println(name);
            jayMetaObject.setValue("name", "昆凌");
            // 昆凌
            System.out.println(jayMetaObject.getValue("name"));
        }
        // 昆凌
        System.out.println(jay.getName());
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# 2.2 嵌套对象操作

    @AllArgsConstructor
    @ToString
    public static class Person {

        @Getter(AccessLevel.PRIVATE)
        @Setter(AccessLevel.PRIVATE)
        private String name;

        @Getter(AccessLevel.PRIVATE)
        @Setter(AccessLevel.PRIVATE)
        private int age;

        @Getter(AccessLevel.PRIVATE)
        @Setter(AccessLevel.PRIVATE)
        private Long userId;
    }
    
    @AllArgsConstructor
    @ToString
    public static class School {

        @Getter(AccessLevel.PRIVATE)
        @Setter(AccessLevel.PRIVATE)
        private String name;

        @Getter(AccessLevel.PRIVATE)
        @Setter(AccessLevel.PRIVATE)
        private Person person;
    }
    
    @Test
    public void fillChildObjectTest() {
        School school = new School("西天大学", new Person("周杰伦", 40, 1L));
        MetaObject schoolMetaObject = MetaObject.forObject(school, new DefaultObjectFactory(), new DefaultObjectWrapperFactory(), new DefaultReflectorFactory());
        // 周杰伦
        System.out.println(schoolMetaObject.getValue("person.name"));
        schoolMetaObject.setValue("person.name", "昆凌");
        // 昆凌
        System.out.println(school.getPerson().getName());
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

# 三、获取反射信息 MetaClass

MetaClass 主要是对 Reflector信息的一个包装并提供些更高级的操作。如跟嵌套类赋值

    @Test
    public void metaClassTest() throws Exception {
        MetaClass metaClass = MetaClass.forClass(School.class, new DefaultReflectorFactory());
        // class com.test.tool.MetaObjectTest$Person
        System.out.println(metaClass.getGetterType("person"));

        School school = new School();
        Invoker setNameInvoker = metaClass.getSetInvoker("name");
        // 通过反射给空对象赋值
        setNameInvoker.invoke(school, new Object[]{"Jay"});

        // 通过反射获取空对象
        Invoker getNameInvoker = metaClass.getGetInvoker("name");
        // Jay
        System.out.println(getNameInvoker.invoke(school, new Object[]{}));
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

本文由西魏陶渊明版权所有。如若转载,请注明出处:西魏陶渊明
上次编辑于: 2022年7月12日 20:38
贡献者: lxchinesszz