springboot集成mybatis源码分析-mybatis的mapper执行查询时的流程(三)
例:
package com.example.demo.service; import com.example.demo.dao.UserDao; import com.example.demo.domain.User; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service @Slf4j public class UserService { @Autowired private UserDao userDao; public List<User> getUser(){ List<User> userList = userDao.getUser(); log.info("查询出来的用户信息,{}",userList.toString()); return userList; } }
当userService中的getUser方法执行的时候,userDao.getUser()是怎么走的?
1、在springboot项目启动时,加载mybatis相关配置,同事会在MapperRegister中保存mapper的代理类,在创建UserService bean的时候,需要注入userDao类,但userDao类是一个Interface类型,所以在注入的时候其实是注入的一个mapper代理类,也就是MapperProxy类
2、当执行userDao.getUser()时,会走MapperProxy中的invoke方法,最终是通过mapperMethod.execute(sqlSession. args)
3、进入MapperMethod的execute方法,会根据select、insert、update 来走不同的方法
4、本次测试时走的是SELECT 的case,在该case中会判断是否有返回值(返回值得处理器),因本次查询返回值是一个list,所以会走executeForMany()
5、进入到executeForMany中,参数是SQLSessionTemplate和null,进行处理后,进入到sqlsession.<E>selectList(*, *)中
6、该selectList方法调用的是SQLSessionTemplate类的selectList
7、进入到sqlSessionProxy(该代理类其实就是DefaultSqlSession)的selectList方法中,参数statement就是mapper方法,paramter为null,
在selectList方法中,会从Configuration对象中获取statement对应的对象,然后通过执行器executor的query来执行
8、进入到executor的query方法中,当前的executor默认是CachingExecutor
9、进入到CachingExecutor的query方法中,在当前方法中会先获取相应的BindSql,然后会创建cache
10、进入到createCacheKey方法中,该方法其实是BaseExecutor中的方法
11、创建完成之后,会调用query方法,在方法中,会先查询cache,没有再调用delegate的query方法
12、delegate是BaseExecutor(执行器),在当前方法中也会先从缓存中查询,查询不到在从库中查询
13、进入queryFormDatabase方法中,在方法中会将之前创建的cacheKey保存到localCache中,然后在执行doQuery方法
14、进入到doQuery方法中,也就是默认的simpleExecutor中
15、进入到configuration.newStatementHandler中(默认statement为preparedStatement)
16、返回preparestatementHandler处理器,然后调用prepareStatement方法
18、在方法中会通过prepareStatement的execute来查询数据库,完毕后,会在handeler中处理返回数据
19、处理返回数据是在DefaultResultSetHandler类中
20、处理完成后悔返回一个list<Object>对象