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的反射模块是整个框架的基石,它通过精心设计的架构和巧妙的缓存机制,为我们提供了高效、灵活的对象操作能力。
相关推荐
Yyyyyy~5 分钟前
【java】数组的定义和使用
java
麻辣布丁6 分钟前
java集合篇面试模拟
java·开发语言·面试
niucloud-admin7 分钟前
JAVA V6 多商户商城 开发文档——插件开发规范
java·开发语言
嘟哩DuliDuli20 分钟前
创作 Agent 的任务状态该如何保存
android·java·javascript
wdfk_prog33 分钟前
lely-canopen-rtt:为什么推荐在 RT-Thread 上使用 Lely CANopen 构建主站
java·运维·缓存·docker·容器
Token掘金室38 分钟前
JSON模式结构化输出报错
java·服务器·json
秋饼44 分钟前
Spring AI 2.0 接入 DeepSeek V4.1 Flash 生产级实战
java·ai·技术分享·后端开发
IT枫斗者枫哥44 分钟前
Java 分批导出仍然 OOM?用 32 MiB 堆复现三种 CSV 写法
java
shehuiyuelaiyuehao1 小时前
算法43,外观数列,模拟算法+双指针
java·算法
lhldsg1 小时前
多商户团购系统源码:技术架构选型与二次开发实战指南
java·小程序·架构