因爲使用spring管理bean,當咱們在代碼中須要使用這個bean的時候,會首先去容器中找,第一次須要調用MapperFactoryBean的getObject方法獲取一個bean,並保存到容器中。spring
MapperFactoryBean的getObject方法以下:sql
因爲每一個MapperFactoryBean對象初始化的時候,都會建立一個sqlSession,代碼在MapperFactoryBean類的父類SqlSessionDaoSupport中,當spring向MapperFactoryBean對象中注入SqlSessionFactory時就建立了SqlSession:數據庫
【結論1】:一個MapperFactoryBean對象擁有一個sqlSession對象。類型是org.mybatis.spring.SqlSessionTemplate緩存
重要:spring整合mybatis使用的sqlSession類型是org.mybatis.spring.SqlSessionTemplate,session
那麼整合後的mybatis是怎麼執行的呢?mybatis
首先查看SqlSessionTemplate類能夠看到,全部的數據庫執行都被一個動態代理的sqlsession對象代理了。app
在構造方法中查看該代理對象的構造spa
使用JDK動態代理,實現InvocationHandler的類是SqlSessionIntercepteor,查看它的invoke方法以下:3d
能夠看到,方法開始就直接建立了一個新的sqlsession對象,這個對象就是被代理的對象。代理
再看getSqlSession方法,它是SqlSessionUtils中的一個靜態方法,以下:
第一句話和事務有關,若是它返回空,則直接使用sessionFactory建立一個新的session
【結論】spring整合mybatis後,非事務環境下,每次操做數據庫都使用新的sqlSession對象。所以mybatis的一級緩存沒法使用(一級緩存針對同一個sqlsession有效)
下面兩段代碼:
(1)不整合spring,以下代碼的輸出能夠看出,使用了一級緩存
結果:查詢過程只執行了一次。
(2)整合spring,
輸出結果以下:
兩次的輸出表示沒有使用一級緩存。
經過getObject返回的對象是單利的,從MapperFactoryBean的isSingleton()能夠得出
【結論二】所以,同一個IOC容器中同一個Mapper接口對應的代理類只有一個
例如系統有一個UserMapper接口對應UserMapper.xml
則以下代碼返回true