mybatis源码解析一,二,三

图1

<mapper resource="org/mybatis/example/BlogMapper.xml">

mybatis解析mapper有几种形式。有四种。第一种<mapper resource> 第二种<mapper url=> ,第三种<mapper package> ,第四种<class>

图2

读取配置mybtis-config.xml的配置文件。构建sqlSessionFactory, 建了SqlSession, 添加userMapper。

图3

图4

图5

 

图6

图7

图8

图9

getMapper(). 产生一个代理类返回。 单个mybatis 的源码过程。因为没有和spring整合,单纯分析的意义不大,不作为重点解析。

图9-0

图9-1

 




mybatis +spring时的mybatis源码解析。

1个问题mybatis在spring环境的情况下缓存失效问题。

2.问题mybatis 一级缓存底层原理。

 

1一级缓存的失效原理。

图1

图1-0

图2

运行结果打印两条sql语句,证明缓存失效。 userMapper是一个接口图1-0  userMapper通过一个代理类来实现的。

图3 

图4

图4-0

图4-1

图5

  MapperFactoryBean是spring 为每个接口文件产生的代理了类, getObject()获取每个接口的代理对象。

图7

图8

图9

图10

图11

此时的mapperInterface=com.luban.mapper.UserMapper  , 为userMapper产生代理对象,mapperProxy为invokerHandle  .

图12

  mapperMethod相当于bd。有方法的相关信息。图13 通过这个mapperMethod可以拿到缓存的级别,sql等等信息。 seqSession ='SqlSessionTemplate'  如果是 单独mybatis时,seqSession='DefaultSqlSession' 具体的对象,图图16-1

图12-1

如果是sqlSession= sqlSessionTEmplate时,他不是自己去执行,而是那到sqlSessionProxy的代理类去执行。图16   

图12-0

sqlSession 的三个实现类DefaultSqlSession(单独的mybatis使用),SqlsessionManager,SqlSessionTemplate(在spring环境下使用)

图12-1

SqlSessionTemplate实例化。

图12-2

图12-3

图12-4

在在创建userMapper的时候,实际new MapperFactoryBean ,如图12-4 mbd 的beanClass 为MapperFactoryBean。

图12-5

mapperInterface 需要自动装配吗?不需要。自动装配会忽略Class类型。String类型等等

 

图12-6

图12-7

图12-8

图12-9

图12-10

图12-11

图12-12

图12-13

图12-14

图12-15

图13

图14

来判断查询的是多条,还是map类型,

图15

 判断是不是有列,如果是spring环境下的,此时的sqlSession为SqlSessionTemplate   。如果单独的mybatis下的是DefaultSqlSession 图16 ,图16-1,图16-2

图16

代理对象 seqSessionProxy

图16-1

图16-2 

图17-0

图17

这个sqlSession 是DefaultSqlSession 。这个method是selectList 被代理的方法,

总结:

在spring环境下 , SqlSessionTemplate  通过调用seqSessionProxy属性的 selectList对象,执行invoke方法实现来代理DefaultSqlSession的对象的selectList()方法,达到对改方法的增强目的,增强就是把session关闭了。因为执行完这个查询置后关闭了DefalutSeqlSession对象,所以一级缓存失效了。

而单独的mybatis中  直接通过DefaultSqlSession 对象的,selectList()方法执行了。该对象。

图18两种情况的比较。

454行关闭sqlsession.

图18

因为我们在整合mybatis和spring的时候,mybatis提供一个插件包叫mybatis-spring,在这个插件包中提供SqlSessionTemplate类 替代了mybatis默认的DefaultSqlSession类,代理了DefaultSqlSession 的方法对象,对DdfaultSqlSession对象的方法进行了增强,增强的过程中把session关闭了。

问题来了,为什么要关闭session呢? 因为spring  他没有办法关,不在这里关就没有地方关,也就是没有暴露相关的api让我们关,而单独的mybatis可以随意关,他有相应的api

图19

图20

图21

mapper在实例化对象的时候就已经把sql等信息,放在map中了。

图21-0

图21-1

图22

图23 

 

图24

MapperFactoryBean  extends SqlSessionDaoSupport  extends DaoSupport  。MapperFactoryBean 在实例化后调用 DaoSupport的afterPropertiesSet() 。DaoSupport的afterPropertiesSet() 方法里调用this.checkDaoConfig(),但是在DaoSupport类这个方法是抽象方法古调用子类;SqlSessionDaoSupport 实现了 checkDaoConfig()方法。MapperFactoryBean也实现了checkDaoConfig方法();最终调用了MapperFactoryBean也实现了checkDaoConfig方法;在这个方法usermapper类传进去注解,sql等信息解析。

图25

 

图26

图27

注册userMapper类。

图28

解析userMapper类的注解。

总结: 问在spring环境中mybatis是怎么初始化的? 他是利用了spring中InitializingBean类 的afterPropertiesSet() 。因为他最终实现了InitializingBean的类,从写了afterPropertiesSet()方法。afterPropertiesSet()方法中完成了mybatis的初始化 图29详细过程。

为什么要这样做呢?

图29

图30-0

执行所有的初始化BeanPostProcessors.执行完后才执行 初始化方法  为什么啊,因为invokeInitMethods 主要执行的afterPropertiesSet()意思是所有类的属性全部se完后执行。因为这些属性对象有可能依赖其他对象。等所有的对象都依赖完成之后才能解析这些,sql,和注解信息。举例图

图30-1

当spring初始化完成以后要执行初始化方法。

图31

同过比较确实init要早于afterPropertiesSet()方法执行。

整个流程图32

图32

 

图33

自动装配的几种类型,AUTOWIRE_NO ,AUTOWIRE_BY_NAME,AUTOWIRE_BY_TYPE。默认为AUTOWIRE_NO 。默认AUTOWIRE_NO不自动装配,只有你在属性上加了 @Autowire 或者@ Resource 注解是才会自动装配 图34。如果使用AUTOWIRE_BY_TYPE是根据属性的set方法的,即便是不加@Autowire 或者@ Resource ,加了set方法也可以完成装配 图35。

图34

这个是加了注解的

图35

AUTOWIRE_BY_TYPE  的情况下,只要属性有set方法就可以实现自动装配 ,有没有属性也没有关系。

那mybatis默认使用的是什么呢,图4-1.使用的是AUTOWIRE_BY_TYPE。为什么这么麻烦那为什么不能 直接使用注解来代替这种MapperScannerRegistrar 这种方式。这样为了解耦,为了更少的依赖spring。

图36

MapperFacoryBean需要装配的属性只有一个是addToCofig属性。

图37

父类有一个setSqlSessionFactory 需要自动装配。 问题来了,那这个sqlSessionFactory什么时候示例话的,在图38进行的示例话。

现在分析一下究竟什么样的属性要被by_type自动装配呢,

图37-1

通过图37-1我们可以目前需要自动装配的有四个属性,一个 setSqlSessionTemlate, setSessionFatory,setAddToConfig,setMapperInterface。 MapperInterface是Class类型过滤调不自动装配,我们看下代码。

图37-2

图37-2通过堆栈信息我们看到首先通过getBean获取到Service,spring 发现他的依赖类 userMapper 然后通过getBean获取UserMapper类。自动装配他的属性填充属性。最终结果是注入了这两个。setSessionFatory,setAddToConfig 从什么地方开始注入的呢,又是从什么地方开始过滤呢,

图37-3

图37-3 开始注入,但是为什么开始注入的时候就有一个addToConfig的属性呢,图37-4添加的;通过观察 经过1170行,pvs由1个变为2个.说明在这个autowireByType中进行的处理。图37-5

图37-4

 

图37-5

图37-5  到propertyNames字符串是我们发现有两个值了 sqlSessionFactory,sqlSessionTemplate。为什么没有Class类型的

图37-6


addToConfig

class  Object类的。

maperInterface

getObect();

getObjetType();

sqlSession

剩下的两个就是返回的那两个 sqlSessionFactory,sqlSessionTemplate

图37-6  这个方法的就是判断哪些类需要自动装配。pvs 目前只有一个是addToConfig 通过外部设置给spring的。pds 属性描述器,一共有9个。那什么为readMethod ,什么是WriterMethod呢, 有get方法的属性成为read,有set方法的属性称为 writerMethod,pds通过判断有没有set方法过滤调除sqlSessionFactory,sqlSessionTemplate,addToConfig,maperInterface 四个类,又通过!pvs .contains(pd.getName())过滤调addToConfig。通过isSimpleValueType()方法过滤调maperInterface 最后只剩下sqlSessionFactory,sqlSessionTemplate 需要自动装配。

图37-7

这个构造器注入的是一个字符串类型,但是spring需要的是一个Class类型。这中间是怎么转化的呢,

图37-8

图37-8

图38

图39

 

总体流程:userMapper 在示例化之前,通过@MapScan  利用ImportBeanDefinitionRegistar类把UserMaper变成MapperFactoryBean;在示例化工程mybatis会产生两个代理对象,一个是Mapper的代理对象,往mapper对象注入一个SqlSessionTemplate 。有了SqlSessionTemplate就可以执行代理了,代理就把session关了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值