Mybatis源码解析之四 mybatis执行流程

本文主要解析Mybatis的执行流程,从Mapper接口的调用到动态生成的MapperProxy对象,详细阐述了SqlSession、Executor、StatementHandler、ParameterHandler、ResultSetHandler、TypeHandler等核心组件的作用。通过对MapperProxy的invoke()方法的分析,揭示了Mybatis如何处理CRUD操作,并对不同类型的Executor进行了对比,包括SimpleExecutor、BatchExecutor和ReuseExecutor的工作原理。
摘要由CSDN通过智能技术生成

目录

 

一、缘起

二、示例代码

  1、mybatis单独测试操作代码

   2、spring与mybatis的整合操作代码

3、 总结

三、mybatis执行流程

 1、mybatis的架构设计图

 2、mybatis的执行流程图

 3、mybatis执行流程时序图

 4、Mybatis的核心组件

 5、mybatis执行流程的分析


一、缘起

     前三篇的文章主要介绍了Mybatis配置以及在spring整合中核心组件SqlSessionFactory对象的创建过程(其中包括了相关子节点的加载,Mapper.xml的加载)。这篇博文主要用来介绍针对Mybatis的curd操作的整个执行流程。因为mybatis单机是对jdbc操作的封装,笔者的分析只到jdbc操作流程(算是mybatis源码的浅尝辄止)。

二、示例代码

  1、mybatis单独测试操作代码

 @Test
    public void testMapper() throws IOException {
        String resource="mybatis-config.xml";
        //以流的方式获取recource(mybatis的环境配置文件)
        InputStream inputStream= Resources.getResourceAsStream(resource);
        //创建会话工厂
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
        //通过工厂得到SqlSession
        SqlSession sqlSession= sqlSessionFactory.openSession();
        //从创建的SqlSession对象中获取Mapper对象 (这个是核心,因为只有拿到该对象的Mapper对象
       //(其实是Mapper接口的代理MapperProxy对象实例))
        BookMapper bookMapper = sqlSession.getMapper(BookMapper.class);

        int bookId = 1000;
        BookExample bookExample = new BookExample();
        bookExample.createCriteria().andIdEqualTo(bookId);
        List<Book> books = bookMapper.selectByExample(bookExample);

    }

   2、spring与mybatis的整合操作代码

	@Autowired
	private BookMapper bookDao;

	@Test
	public void testQueryById() throws Exception {
		int bookId = 1000;
		BookExample bookExample = new BookExample();
		bookExample.createCriteria().andIdEqualTo(bookId);
		List<Book> books = bookDao.selectByExample(bookExample);
	}

3、 总结

          如上两种方式前者使用代码显示的从SqlSession对象中获取Mapper代理对象,后者则是在spring容器启动后将Mapper对象创建放入Spring容器中进行托管。这里有个疑问在于我们编写的XxxMapper为接口,但是在使用过程中初始化了其相应的Mapper代理对象。这里我们就来分析一下。

  3.1、MapperProxy对象

       这里不卖关子了,其实Mybatis为我们动态的生成了XxxMapper对象的的代理对象类为MapperProxy,熟悉JDK动态代理的同学都知道接口中所有的实现都是调用实现了InvocationHandler对象的invoke()方法,我们所有对XxxMapper接口中方法的调用最终都会调用invoke()方法。上面的两个测试(一个单独测试,一个spring整合测试)该对象生成过程之间略有差异,前者是使用DefaultSqlSession的getMapper方法来生成,而后者则是使用SqlSessionTemplate对象的getMapper()方法生成。这里我们来对该MapperProxy对象初始化来做分析。

    public <T> T getMapper(Class<T> type) {
        //通过Configuration对象获取其中的mapper
        return this.getConfiguration().getMapper(type, this);
    }

  configuration对象是我们mybatis的所有配置的对象,通过调用其getMapper()方法来获取MapperProxy,但是实际操作是被委托给了MapperRegistry对象。

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
  //通过configuration对象中的MapperRegistry对象调用其中的getMapper方法
  return mapperRegistry.getMapper(type, sqlSession);
}

   mapperRegistry根据对应的XxxMapper类class信息以及对应的mybatis会话sqlSession对象来获取dao层代理对象。还使用到了我们初始化Mapper.xml对象的时候将其以 XxxMapper className为key,MapperProxyFactory为value的形式存放在Map类型的结构对象knownMappers中,所以此处获取到对应的MapperProxyFactory对象(该对象中包含了XxxMapper接口类信息),通过Jdk动态代理生成XxxMapper接口的动态dialing对象

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
   //从map容器中获取MapperProxyFactory对象信息 
   final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
    if (mapperProxyFactory == null) {
      throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    }
    try {
      //调用map中获取的MapperProxyFactory对象 实例化Mapper动态代理对想
      return mapperProxyFactory.newInstance(sqlSession);
    } catch (Exception e) {
      throw new BindingException("Error getting mapper instance. Cause: " + e, e);
    }
  }


//JDK动态代理实例化dao接口对象

 protected T newInstance(MapperProxy<T> mapperProxy) {
    //jdk动态代理
    return (T) Proxy.ne
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值