例:
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>對象