深入理解MyBatis核心基础设施,掌握对象操作的本质原理
引言
在使用MyBatis进行开发时,你是否好奇过:
MyBatis如何将ResultSet数据自动映射到Java对象? 它是如何在运行时动态操作对象属性的? 为什么MyBatis能够处理各种复杂的嵌套属性?一、MyBatis整体架构与反射模块
1.1 反射模块在MyBatis中的位置
MyBatis整体架构
从架构图可以看出,MyBatis采用了分层设计,而反射模块(Reflection)位于基础支撑层,是整个框架的核心基础设施。
1.2 反射模块的五大核心职责
✅ 对象属性访问 - 通过反射读写对象属性 ✅ 对象实例化 - 动态创建对象实例 ✅ 类型解析 - 分析类的类型信息 ✅ 元数据获取 - 获取方法、字段、构造器等元数据 ✅ 性能优化 - 缓存反射信息,提升性能1.3 为什么需要反射模块?
场景1:结果映射
ResultSet → 提取数据 → 通过反射设置到Java对象
场景2:参数传递
Java对象 → 通过反射获取属性值 → 设置到PreparedStatement
场景3:对象创建
Mapper返回类型 → 通过反射创建实例 → 填充数据
场景4:元数据解析
XML配置 → 解析类名 → 通过反射获取类信息
没有反射模块,这些操作都需要手工编写大量重复代码!
1.4 Java反射基础回顾
// 获取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负责创建对象实例,定义了简单而强大的接口:
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核心代码:
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
核心代码:
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); } }使用示例:
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: city2.4 PropertyCopier - 属性复制器
PropertyCopier用于在对象间复制属性:
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是反射模块的核心类,用于缓存类的反射信息。
核心结构:
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方法的核心逻辑:
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:
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:
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创建对象
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处理接口和抽象类:
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提供统一的属性访问接口:
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实现示例:
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 - 泛型解析
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 - 类型别名
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 - 类型处理器
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 获取类信息
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 获取方法信息
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 - 工厂模式
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 常见问题解决
// 错误原因:属性名不匹配 // 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反射模块的设计思想:
缓存优化 - 缓存反射信息,避免重复解析 封装复杂度 - 封装Java反射API,简化使用 统一接口 - 通过MetaObject提供统一操作接口 扩展性强 - 支持Map、Collection等多种对象类型 性能优先 - 反射信息只解析一次并缓存MyBatis的反射模块是整个框架的基石,它通过精心设计的架构和巧妙的缓存机制,为我们提供了高效、灵活的对象操作能力。