第14篇:Mybatis中反射工具

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

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);
    }
  }
  
}  

二、通过反射操作对象 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());
    }

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());
    }

三、获取反射信息 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[]{}));
    }
相关文章
|
5月前
|
SQL Java 数据库
深入解析MyBatis-Plus中静态工具Db的多种用法及示例
深入解析MyBatis-Plus中静态工具Db的多种用法及示例
499 0
|
5月前
|
SQL Java 数据库连接
Mybatis和MybatisPlus:数据库操作工具的对比
Mybatis和MybatisPlus:数据库操作工具的对比
370 0
|
4月前
|
Java 数据库连接 API
后端开发之用Mybatis简化JDBC的开发快速入门2024及数据库连接池技术和lombok工具详解
后端开发之用Mybatis简化JDBC的开发快速入门2024及数据库连接池技术和lombok工具详解
55 3
|
5月前
|
XML Java 数据库连接
一起剖析Mybatis初始化过程中的六个牛逼工具
一起剖析Mybatis初始化过程中的六个牛逼工具
25 0
Mybatis-plus-generator代码自动生成工具
Mybatis-plus-generator代码自动生成工具
85 0
|
5月前
|
数据库连接
一款非常好用的MyBatisPlus代码生成工具
一款非常好用的MyBatisPlus代码生成工具
31 0
|
5月前
|
SQL Java 数据库连接
myabtis中为什么说 MyBatis 是半自动 ORM 映射工具?它与全自动的区别在哪里
myabtis中为什么说 MyBatis 是半自动 ORM 映射工具?它与全自动的区别在哪里
|
5月前
|
Oracle Java 关系型数据库
mybatis快速自动生成代码【采用工具,开箱即用】
mybatis快速自动生成代码【采用工具,开箱即用】
|
5月前
|
安全 前端开发 Java
Java反射详解,学以致用,实战案例(AOP修改参数、Mybatis拦截器实现自动填充)3
Java反射详解,学以致用,实战案例(AOP修改参数、Mybatis拦截器实现自动填充)
107 0
|
5月前
|
Java 数据库连接 API
Java反射详解,学以致用,实战案例(AOP修改参数、Mybatis拦截器实现自动填充)2
Java反射详解,学以致用,实战案例(AOP修改参数、Mybatis拦截器实现自动填充)
69 0