因为使用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