MyBatis反射模块详解

深入理解MyBatis核心基础设施,掌握对象操作的本质原理

引言

在使用MyBatis进行开发时,你是否好奇过:

复制代码
MyBatis如何将ResultSet数据自动映射到Java对象?
它是如何在运行时动态操作对象属性的?
为什么MyBatis能够处理各种复杂的嵌套属性?

一、MyBatis整体架构与反射模块

1.1 反射模块在MyBatis中的位置

从架构图可以看出,MyBatis采用了分层设计,而反射模块(Reflection)位于基础支撑层,是整个框架的核心基础设施。

1.2 反射模块的五大核心职责

复制代码
✅ 对象属性访问 - 通过反射读写对象属性 
✅ 对象实例化 - 动态创建对象实例 
✅ 类型解析 - 分析类的类型信息
✅ 元数据获取 - 获取方法、字段、构造器等元数据 
✅ 性能优化 - 缓存反射信息,提升性能

1.3 为什么需要反射模块?

场景1:结果映射

ResultSet → 提取数据 → 通过反射设置到Java对象

场景2:参数传递

Java对象 → 通过反射获取属性值 → 设置到PreparedStatement

场景3:对象创建

Mapper返回类型 → 通过反射创建实例 → 填充数据

场景4:元数据解析

XML配置 → 解析类名 → 通过反射获取类信息

没有反射模块,这些操作都需要手工编写大量重复代码!

1.4 Java反射基础回顾

ini 复制代码
// 获取Class对象
Class<?> clazz = User.class;

// 创建实例
Object obj = clazz.newInstance();

// 获取方法
Method method = clazz.getMethod("setName", String.class);

// 调用方法
method.invoke(obj, "张三");

// 获取字段
Field field = clazz.getDeclaredField("name");
field.setAccessible(true);
field.set(obj, "张三");

二、反射模块架构

2.1 反射模块组成

Reflection(反射模块)

├── ObjectFactory(对象工厂)

├── PropertyTokenizer(属性分词器)

├── PropertyCopier(属性复制器)

├── Reflector(反射器)

├── MetaClass(元数据类)

├── MetaObject(元对象)

└── SystemMetaObject(系统元对象)

2.2 ObjectFactory - 对象工厂

ObjectFactory负责创建对象实例,定义了简单而强大的接口:

typescript 复制代码
public interface ObjectFactory {
    // 创建对象实例
    <T> T create(Class<T> type);

    // 创建对象实例(带构造参数)
    <T> T create(Class<T> type, 
                 Class<?>[] classes, 
                 Object[] values);

    // 判断是否为集合类型
    <T> boolean isCollection(Class<T> type);
}

默认实现DefaultObjectFactory核心代码:

typescript 复制代码
public class DefaultObjectFactory implements ObjectFactory {
    @Override
    public <T> T create(Class<T> type) {
        try {
            return type.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(
                "Error creating instance of " + type, e);
        }
    }

    @Override
    public <T> T create(Class<T> type, 
                        Class<?>[] classes, 
                        Object[] values) {
        try {
            // 查找匹配的构造器
            Constructor<?> constructor = 
                type.getDeclaredConstructor(classes);
            constructor.setAccessible(true);
            return (T) constructor.newInstance(values);
        } catch (Exception e) {
            // 处理异常...
        }
        return create(type);
    }

    @Override
    public <T> boolean isCollection(Class<T> type) {
        return Collection.class.isAssignableFrom(type) 
               || type.isArray();
    }
}

2.3 PropertyTokenizer - 属性分词器

PropertyTokenizer用于解析复杂的属性表达式,比如user.address.city

核心代码:

ini 复制代码
public class PropertyTokenizer 
    implements Iterator<PropertyTokenizer> {

    private String fullname;      // 完整属性表达式
    private String name;          // 当前名称
    private String indexedName;   // 索引名称
    private String index;         // 索引值
    private String children;      // 子属性

    public PropertyTokenizer(String fullname) {
        this.fullname = fullname;

        // 解析属性表达式
        int delim = fullname.indexOf('.');
        if (delim > -1) {
            name = fullname.substring(0, delim);
            children = fullname.substring(delim + 1);
        } else {
            name = fullname;
            children = null;
        }

        indexedName = name;
        // 解析索引 例如:list[0]
        delim = name.indexOf('[');
        if (delim > -1) {
            index = name.substring(delim + 1, 
                                   name.length() - 1);
            name = name.substring(0, delim);
        }
    }

    @Override
    public boolean hasNext() {
        return children != null;
    }

    @Override
    public PropertyTokenizer next() {
        return new PropertyTokenizer(children);
    }
}

使用示例:

ini 复制代码
String expression = "user.address.city";
PropertyTokenizer tokenizer = 
    new PropertyTokenizer(expression);

while (tokenizer.hasNext()) {
    System.out.println(
        "Current: " + tokenizer.getName());
    tokenizer = tokenizer.next();
}

// 输出:
// Current: user
// Current: address
// Current: city

2.4 PropertyCopier - 属性复制器

PropertyCopier用于在对象间复制属性:

scss 复制代码
public class PropertyCopier {
    public void copyProperties(Object source, 
                               Object target) {
        // 获取元数据
        MetaClass sourceMetaClass = 
            MetaClass.forClass(source.getClass());
        MetaClass targetMetaClass = 
            MetaClass.forClass(target.getClass());

        // 获取源对象的所有属性
        String[] getterNames = 
            sourceMetaClass.getGetterNames();

        for (String name : getterNames) {
            // 检查目标对象是否有对应的setter
            if (targetMetaClass.hasSetter(name)) {
                try {
                    // 复制属性值
                    Object value = sourceMetaClass
                        .getGetter(name)
                        .invoke(source);
                    targetMetaClass
                        .getSetter(name)
                        .invoke(target, value);
                } catch (Exception e) {
                    // 忽略无法复制的属性
                }
            }
        }
    }
}

三、对象属性访问

3.1 Reflector - 反射器

Reflector是反射模块的核心类,用于缓存类的反射信息。

核心结构:

swift 复制代码
public class Reflector {
    // 类类型
    private final Class<?> type;

    // 可读属性映射:属性名 -> getter方法
    private final Map<String, Invoker> getMethods 
        = new HashMap<>();

    // 可写属性映射:属性名 -> setter方法
    private final Map<String, Invoker> setMethods 
        = new HashMap<>();

    // 属性类型映射
    private final Map<String, Class<?>> getTypes 
        = new HashMap<>();
    private final Map<String, Class<?>> setTypes 
        = new HashMap<>();

    // 所有属性名
    private final Set<String> properties 
        = new HashSet<>();

    public Reflector(Class<?> clazz) {
        this.type = clazz;
        addDefaultConstructor(clazz);
        addGetMethods(clazz);
        addSetMethods(clazz);
        addFields(clazz);
    }
}

添加getter方法的核心逻辑:

scss 复制代码
private void addGetMethods(Class<?> clazz) {
    Method[] methods = clazz.getDeclaredMethods();

    for (Method method : methods) {
        // 处理getXxx()方法
        if (method.getName().startsWith("get") 
            && method.getParameterTypes().length == 0) {

            String name = method.getName().substring(3);
            name = Character.toLowerCase(name.charAt(0)) 
                   + name.substring(1);
            addGetMethod(name, method);
        } 
        // 处理isXxx()方法
        else if (method.getName().startsWith("is") 
            && method.getParameterTypes().length == 0
            && method.getReturnType() == boolean.class) {

            String name = method.getName().substring(2);
            name = Character.toLowerCase(name.charAt(0)) 
                   + name.substring(1);
            addGetMethod(name, method);
        }
    }
}

3.2 MetaClass - 元数据类

MetaClass对Reflector进行了封装,提供更友好的API:

typescript 复制代码
public class MetaClass {
    private final Reflector reflector;

    // 获取属性值
    public Object getValue(String name, Object obj) {
        try {
            Invoker method = 
                reflector.getGetInvoker(name);
            return method.invoke(obj);
        } catch (Exception e) {
            throw new RuntimeException(
                "Error getting property '" + name + "'", e);
        }
    }

    // 设置属性值
    public void setValue(String name, 
                        Object obj, 
                        Object value) {
        try {
            Invoker method = 
                reflector.getSetInvoker(name);
            method.invoke(obj, value);
        } catch (Exception e) {
            throw new RuntimeException(
                "Error setting property '" + name + "'", e);
        }
    }

    // 获取属性类型
    public Class<?> getGetterType(String name) {
        return reflector.getGetterType(name);
    }

    // 是否有getter/setter
    public boolean hasGetter(String name) {
        return reflector.hasGetter(name);
    }

    public boolean hasSetter(String name) {
        return reflector.hasSetter(name);
    }
}

3.3 MetaObject - 元对象

MetaObject是元数据的门面类,提供了最友好的API:

typescript 复制代码
public abstract class MetaObject {
    private Object originalObject;
    private MetaClass metaClass;
    private ObjectWrapper objectWrapper;

    // 获取属性值(支持嵌套属性)
    public Object getValue(String name) {
        PropertyTokenizer prop = 
            new PropertyTokenizer(name);

        if (prop.hasNext()) {
            // 处理嵌套属性
            return metaClass.getValue(
                prop.getName(), originalObject);
        } else {
            return objectWrapper.get(prop);
        }
    }

    // 设置属性值(支持嵌套属性)
    public void setValue(String name, Object value) {
        PropertyTokenizer prop = 
            new PropertyTokenizer(name);

        if (prop.hasNext()) {
            metaClass.setValue(
                prop.getName(), originalObject, value);
        } else {
            objectWrapper.set(prop, value);
        }
    }

    // 创建MetaObject
    public static MetaObject forObject(
        Object object,
        ObjectFactory objectFactory,
        ObjectWrapperFactory objectWrapperFactory) {

        if (object == null) {
            return SystemMetaObject.NULL_META_OBJECT;
        }

        // 根据对象类型创建不同的MetaObject
        if (object instanceof Map) {
            return new MapMetaObject(
                (Map) object, 
                objectFactory, 
                objectWrapperFactory);
        } else if (object instanceof Collection) {
            return new CollectionMetaObject(
                (Collection) object,
                objectFactory,
                objectWrapperFactory);
        } else {
            return new BeanMetaObject(
                object,
                objectFactory,
                objectWrapperFactory);
        }
    }
}

四、对象实例化

4.1 ObjectFactory创建对象

ini 复制代码
ObjectFactory objectFactory = 
    new DefaultObjectFactory();

// 创建简单对象
User user = objectFactory.create(User.class);

// 创建带参对象
Class<?>[] classes = {String.class, String.class};
Object[] values = {"张三", "zhangsan@example.com"};
User user = objectFactory.create(
    User.class, classes, values);

// 创建集合
List<User> users = 
    objectFactory.create(ArrayList.class);

4.2 处理特殊类型

扩展ObjectFactory处理接口和抽象类:

typescript 复制代码
public class CustomObjectFactory 
    extends DefaultObjectFactory {

    @Override
    public <T> T create(Class<T> type) {
        // 处理接口类型
        if (type.isInterface()) {
            if (type.equals(List.class)) {
                return (T) new ArrayList<>();
            } else if (type.equals(Map.class)) {
                return (T) new HashMap<>();
            }
            throw new RuntimeException(
                "Cannot create instance of interface: " 
                + type);
        }

        // 处理抽象类
        if (Modifier.isAbstract(type.getModifiers())) {
            throw new RuntimeException(
                "Cannot create instance of abstract class: "
                + type);
        }

        return super.create(type);
    }
}

4.3 对象包装器 - ObjectWrapper

ObjectWrapper提供统一的属性访问接口:

arduino 复制代码
public interface ObjectWrapper {
    // 获取属性值
    Object get(PropertyTokenizer prop);

    // 设置属性值
    void set(PropertyTokenizer prop, Object value);

    // 获取属性类型
    Class<?> getSetterType(String name);

    // 是否有setter/getter
    boolean hasSetter(String name);
    boolean hasGetter(String name);
}

BeanWrapper实现示例:

typescript 复制代码
public class BeanWrapper extends BaseWrapper 
    implements ObjectWrapper {

    private final Object object;
    private final MetaClass metaClass;

    @Override
    public Object get(PropertyTokenizer prop) {
        try {
            Invoker method = metaClass.getGetInvoker(
                prop.getName());
            Object value = method.invoke(object);

            if (prop.hasNext() && value != null) {
                // 递归获取嵌套属性
                return MetaObject
                    .forObject(value, ...)
                    .getValue(prop.getChildren());
            }
            return value;
        } catch (Throwable t) {
            throw new RuntimeException(
                "Error getting property '" 
                + prop.getName() + "'", t);
        }
    }

    @Override
    public void set(PropertyTokenizer prop, 
                    Object value) {
        try {
            if (prop.hasNext()) {
                // 处理嵌套属性
                Object child = get(prop);
                if (child == null) {
                    child = instantiatePropertyValue(
                        prop.getName(), 
                        prop.getChildren());
                    set(prop, child);
                }
                MetaObject
                    .forObject(child, ...)
                    .setValue(prop.getChildren(), value);
            } else {
                Invoker method = metaClass.getSetInvoker(
                    prop.getName());
                method.invoke(object, value);
            }
        } catch (Throwable t) {
            throw new RuntimeException(
                "Error setting property '" 
                + prop.getName() + "'", t);
        }
    }
}

五、类型解析

5.1 TypeParameterResolver - 泛型解析

typescript 复制代码
public class TypeParameterResolverImpl 
    implements TypeParameterResolver {

    private final Type type;

    @Override
    public Type resolveType(Type rawType, Type jniType) {
        // 解析泛型类型
        if (rawType instanceof Class) {
            return resolveClass((Class<?>) rawType);
        } else if (rawType instanceof ParameterizedType) {
            return resolveParameterizedType(
                (ParameterizedType) rawType);
        } else if (rawType instanceof GenericArrayType) {
            return resolveGenericArrayType(
                (GenericArrayType) rawType);
        }
        return rawType;
    }
}

5.2 TypeAliasRegistry - 类型别名

typescript 复制代码
public class TypeAliasRegistry {
    // 别名到类型的映射
    private final Map<String, Class<?>> typeAliases 
        = new HashMap<>();

    // 注册类型别名
    public void registerAlias(String alias, 
                             Class<?> value) {
        if (alias == null) {
            throw new TypeException(
                "Type alias cannot be null");
        }
        typeAliases.put(alias, value);
    }

    // 根据别名解析类型
    public Class<?> resolveAlias(String string) {
        if (string == null) {
            return null;
        }

        String key = string.toLowerCase(Locale.ENGLISH);
        Class<?> value = typeAliases.get(key);

        if (value == null) {
            try {
                return Class.forName(string);
            } catch (ClassNotFoundException e) {
                throw new TypeException(
                    "Could not resolve type alias '" 
                    + string + "'", e);
            }
        }
        return value;
    }
}

5.3 TypeHandlerRegistry - 类型处理器

typescript 复制代码
public class TypeHandlerRegistry {
    // 类型到处理器的映射
    private final Map<Type, Map<JdbcType, TypeHandler<?>>> 
        typeHandlerMap = new HashMap<>();

    // 获取类型处理器
    public <T> TypeHandler<T> getTypeHandler(
        Type type, 
        JdbcType jdbcType) {

        Map<JdbcType, TypeHandler<?>> jdbcTypeHandlerMap 
            = typeHandlerMap.get(type);

        if (jdbcTypeHandlerMap != null) {
            TypeHandler<?> handler = 
                jdbcTypeHandlerMap.get(jdbcType);
            if (handler != null) {
                return (TypeHandler<T>) handler;
            }
        }
        return getTypeHandler(Object.class);
    }
}

六、元数据获取

6.1 获取类信息

csharp 复制代码
public class ClassInfo {
    public static void analyze(Class<?> clazz) {
        System.out.println("类名: " 
            + clazz.getName());
        System.out.println("简单名称: " 
            + clazz.getSimpleName());
        System.out.println("包名: " 
            + clazz.getPackage().getName());
        System.out.println("父类: " 
            + clazz.getSuperclass().getName());
        System.out.println("接口: " 
            + Arrays.toString(clazz.getInterfaces()));

        // 获取修饰符
        int modifiers = clazz.getModifiers();
        System.out.println("是否为public: " 
            + Modifier.isPublic(modifiers));
        System.out.println("是否为abstract: " 
            + Modifier.isAbstract(modifiers));
    }
}

6.2 获取方法信息

typescript 复制代码
public class MethodInfo {
    // 判断是否为getter方法
    private static boolean isGetter(Method method) {
        String name = method.getName();
        return (name.startsWith("get") 
                && name.length() > 3 
                && method.getParameterTypes().length == 0)
            || (name.startsWith("is") 
                && name.length() > 2 
                && method.getParameterTypes().length == 0
                && method.getReturnType() == boolean.class);
    }

    // 判断是否为setter方法
    private static boolean isSetter(Method method) {
        String name = method.getName();
        return name.startsWith("set") 
            && name.length() > 3 
            && method.getParameterTypes().length == 1
            && method.getReturnType() == void.class;
    }

    // 获取属性名
    private static String getPropertyName(Method method) {
        String name = method.getName();
        if (name.startsWith("get") 
            || name.startsWith("set")) {
            name = name.substring(3);
        } else if (name.startsWith("is")) {
            name = name.substring(2);
        }
        return Character.toLowerCase(name.charAt(0)) 
               + name.substring(1);
    }
}

6.3 ReflectorFactory - 工厂模式

typescript 复制代码
public class ReflectorFactory {
    // Reflector缓存
    private final ConcurrentMap<Class<?>, Reflector> 
        reflectorMap = new ConcurrentHashMap<>();

    // 获取Reflector
    public Reflector findForClass(Class<?> type) {
        return reflectorMap.computeIfAbsent(type, k -> {
            return new Reflector(k);
        });
    }

    // 判断是否已有缓存
    public boolean hasReflectorFor(Class<?> type) {
        return reflectorMap.containsKey(type);
    }
}

七、最佳实践

7.1 性能优化建议

复制代码
✅缓存反射信息Reflector自动缓存类的反射信息,避免重复解析
✅避免频繁反射尽量使用MetaObject而非直接使用Java反射API
✅使用对象池在高并发场景下复用对象实例
✅延迟加载只在真正需要时才解析元数据

7.2 使用建议

复制代码
✅ 首选MetaObject提供统一、友好的属性访问接口
✅ 继承BaseWrapper实现自定义的对象包装器时继承BaseWrapper
✅ 扩展ObjectFactory支持特殊类型的实例化需求
✅ 注册类型别名简化XML配置,提升可读性

7.3 常见问题解决

typescript 复制代码
// 错误原因:属性名不匹配
// User类字段:userName
// getter方法:getName() ❌

// 正确做法:确保符合JavaBean规范
public String getUserName() {  ✅
    return userName;
}

public void setUserName(String userName) {
    this.userName = userName;
}
MetaObject metaObject = MetaObject.forObject(user, ...);

// 直接访问
Object address = metaObject.getValue("address");

// 嵌套访问
Object city = metaObject.getValue("address.city");

// 带索引的访问
Object item = metaObject.getValue("orders[0].itemName");
// 使用TypeHandlerRegistry处理类型转换
TypeHandlerRegistry registry = new TypeHandlerRegistry();
TypeHandler<String> handler = 
    registry.getTypeHandler(String.class);

// 设置参数
handler.setParameter(ps, 1, "张三");

// 获取结果
String result = handler.getResult(rs, "name");

八、总结

关键组件

复制代码
🔹ObjectFactory - 对象工厂,负责创建对象实例 
🔹PropertyTokenizer - 属性分词器,解析嵌套属性表达式
🔹 PropertyCopier - 属性复制器,实现对象属性复制 
🔹 Reflector - 反射器,缓存类的反射信息 
🔹 MetaClass - 元数据类,封装Reflector 
🔹 MetaObject - 元对象,提供统一的属性访问接口

设计思想

MyBatis反射模块的设计思想:

javascript 复制代码
💎 缓存优化 - 缓存反射信息,避免重复解析
💎 封装复杂度 - 封装Java反射API,简化使用 
💎 统一接口 - 通过MetaObject提供统一操作接口 
💎 扩展性强 - 支持Map、Collection等多种对象类型 
💎 性能优先 - 反射信息只解析一次并缓存
MyBatis的反射模块是整个框架的基石,它通过精心设计的架构和巧妙的缓存机制,为我们提供了高效、灵活的对象操作能力。
相关推荐
宸津-代码粉碎机2 小时前
Spring 6.0+Boot 3.0实战避坑全指南:5大类高频问题与解决方案(附代码示例)
java·数据仓库·hive·hadoop·python·技术文档编写
笃行客从不躺平2 小时前
ThreadLocal 复习一
java·开发语言
程序帝国2 小时前
SpringBoot整合RediSearch(完整,详细,连接池版本)
java·spring boot·redis·后端·redisearch
安卓程序员_谢伟光2 小时前
如何监听System.exit(0)的调用栈
java·服务器·前端
Pluto_CSND2 小时前
JSONPath解析JSON数据结构
java·数据结构·json
xiaoliuliu123452 小时前
Tomcat Connectors 1.2.32 源码编译安装教程(含 mod_jk 配置步骤)
java·tomcat
CYTElena2 小时前
JAVA关于集合的笔记
java·开发语言·笔记
源码获取_wx:Fegn08952 小时前
基于springboot + vueOA工程项目管理系统
java·vue.js·spring boot·后端·spring
短剑重铸之日2 小时前
《Java并发编程研读》第三章:锁机制
java·java并发编程·java锁机制