开始mybaits源码学习 1

本文深入探讨了MyBatis框架中MapperProxy的实现原理,特别是newMapperProxy方法如何创建动态代理对象,以及MapperMethod类在执行查询操作时的作用。通过解析这些核心组件的工作机制,读者可以更好地掌握MyBatis动态代理机制,提升对框架内部工作的理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    从org.apache.ibatis.binding.MapperProxy开始。

    MapperProxy是一个代理类实现java标准代理接口,私有构造,另提供一个获得动态代理的静态方法。

 

    1. newMapperProxy

  @SuppressWarnings("unchecked")
public static <T> T newMapperProxy(Class<T> mapperInterface, SqlSession sqlSession) {
    ClassLoader classLoader = mapperInterface.getClassLoader();
    Class<?>[] interfaces = new Class[]{mapperInterface};
    MapperProxy proxy = new MapperProxy(sqlSession);
    return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy);
  }

 newMapperProxy是一个java动态代理,支持泛型。mapperInterface就是自己定义的Mapper接口,SqlSession则从外部生成,传入。以后再学习、研究。现在主要来看MapperProxy.invoke。

 

    2.  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable

 

final Class<?> declaringInterface = findDeclaringInterface(proxy, method);
final MapperMethod mapperMethod = new MapperMethod(declaringInterface, method, sqlSession);
final Object result = mapperMethod.execute(args);

 主要是获得被代理对象的接口,委托org.apache.ibatis.binding.MapperMethod执行,并获得结果。重点转到MapperMethod对象。

 

    3.

 

  public MapperMethod(Class<?> declaringInterface, Method method, SqlSession sqlSession) {
   //........
    this.config = sqlSession.getConfiguration();
 }

 在构造方法里将自定义的Mapper接口的方法(方法定义、传参数、返回值、方法相关的注解)与配置文件(config)关联起来:

 

//代码不连续,只选择部分关键代码
//完整的 类名.方法名 组成commandName
 this.commandName = declaringInterface.getName() + "." + method.getName();
//通过commandName关联配置信息
//type为:public enum SqlCommandType { UNKNOWN, INSERT, UPDATE, DELETE, SELECT; }
MappedStatement ms = config.getMappedStatement(commandName);
 type = ms.getSqlCommandType(); 
//参数的注解信息,顺序
paramName = ((Param) paramAnnos[j]).value();
//返回值信息
 if (List.class.isAssignableFrom(method.getReturnType()))

 在Object execute(Object[] args)方法中根据type调用SqlSession不同的方法

 

  public Object execute(Object[] args) {
    Object result = null;
    if (SqlCommandType.INSERT == type) {
      Object param = getParam(args);
      result = sqlSession.insert(commandName, param);
    }//......
    } else if (SqlCommandType.SELECT == type) {
      if (returnsVoid && resultHandlerIndex != null) {
        executeWithResultHandler(args);//取交集 ???
      } else if (returnsList) {
        result = executeForList(args);//委托sqlSession.selectList
      } else if (returnsMap) {
        result = executeForMap(args);//委托sqlSession.selectMap
      } else {    //可能返回一个自定义的类
        Object param = getParam(args);
        result = sqlSession.selectOne(commandName, param);
      }
    return result;
  }

目前为止,自定义的Mapper接口的使命就完成了,所有的查询都交给SqlSession处理。那么SqlSession怎么生成的,怎么处理即成为了重点。

 

a.连接的生成、结果集的封转。

b.配置文件的解析,动态sql生成、缓存、事务

 

1. 用户与身体信息管理模块 用户信息管理: 注册登录:支持手机号 / 邮箱注册,密码加密存储,提供第三方快捷登录(模拟) 个人资料:记录基本信息(姓名、年龄、性别、身高、体重、职业) 健康目标:用户设置目标(如 “减重 5kg”“增肌”“维持健康”)及期望周期 身体状态跟踪: 体重记录:定期录入体重数据,生成体重变化曲线(折线图) 身体指标:记录 BMI(自动计算)、体脂率(可选)、基础代谢率(根据身高体重估算) 健康状况:用户可填写特殊情况(如糖尿病、过敏食物、素食偏好),系统据此调整推荐 2. 膳食记录与食物数据库模块 食物数据库: 基础信息:包含常见食物(如米饭、鸡蛋、牛肉)的名称、类别(主食 / 肉类 / 蔬菜等)、每份重量 营养成分:记录每 100g 食物的热量(kcal)、蛋白质、脂肪、碳水化合物、维生素、矿物质含量 数据库维护:管理员可添加新食物、更新营养数据,支持按名称 / 类别检索 膳食记录功能: 快速记录:用户选择食物、输入食用量(克 / 份),系统自动计算摄入的营养成分 餐次分类:按早餐 / 午餐 / 晚餐 / 加餐分类记录,支持上传餐食照片(可选) 批量操作:提供常见套餐模板(如 “三明治 + 牛奶”),一键添加到记录 历史记录:按日期查看过往膳食记录,支持编辑 / 删除错误记录 3. 营养分析模块 每日营养摄入分析: 核心指标计算:统计当日摄入的总热量、蛋白质 / 脂肪 / 碳水化合物占比(按每日推荐量对比) 微量营养素分析:检查维生素(如维生素 C、钙、铁)的摄入是否达标 平衡评估:生成 “营养平衡度” 评分(0-100 分),指出摄入过剩或不足的营养素 趋势分析: 周 / 月营养趋势:用折线图展示近 7 天 / 30 天的热量、三大营养素摄入变化 对比分析:将实际摄入与推荐量对比(如 “蛋白质摄入仅达到推荐量的 70%”) 目标达成率:针对健
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值