mybatis源码解析--mapper代理对象的生成过程

我们平常在使用mybatis的时候只需要生成mapper接口和与其对应的xml文件就行了,我们就可以把这个接口当作一个bean,可以往其他的bean中注入了。我们没有实现mapper接口,为什么可以使用接口中的方法呢?原因是虽然我们没有实现接口,但是通过配置文件,spring为我们生成了接口的代理类。
让我们从配置文件入手,从源码中一探究竟。
在这里插入图片描述
MapperScannerConfigurer这个类是负责扫描mapper接口所在的包的,它把扫描到的接口解析成一个个的bean定义(BeanDefinition),来看一下源码:
在这里插入图片描述
MapperScannerConfigurer实现了两个重要接口,如图所示。
实现BeanDefinitionRegistryPostProcessor接口,我们可以自定义注册bean过程,要实现的方法是
postProcessBeanDefinitionRegistry()
实现InitializingBean接口的afterPropertiesSet()方法,可以在bean创建之后初始化的时候做一些操作。
现在进入MapperScannerConfigurer的postProcessBeanDefinitionRegistry()方法
在这里插入图片描述
该方法内部把扫描mapper接口的工作委托给了ClassPathMapperScanner类,该类继承自ClassPathBeanDefinitionScanner,进入它的scan()方法:
在这里插入图片描述
ClassPathBeanDefinitionScanner中的doScan()方法:
在这里插入图片描述
doScan方法真正的负责生成bean定义。
ClassPathMapperScanner重载的doScan()方法:
在这里插入图片描述
重载的doScan方法对生成的mapper的bean定义做了进一步处理,进入processBeanDefinitions()方法:
在这里插入图片描述
红色部分为该方法的核心,mapperInterface设置的值是mapper接口的带包名的路径名称;
definition.setBeanClass()把原来的BeanClass的类型替换成了MapperFactoryBean类型,这个是Mapper接口加载定义阶段最重要的一步。是生成代理类的关键。
查看MapperFactoryBean的定义:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
MapperFactoryBean实现了FactoryBean接口,实现了FactoryBean接口的类型在调用getBean(beanName)既通过名称获取对象时,返回的对象不是本身类型的对象,而是通过实现接口中的getObject()方法返回的对象。
在这里插入图片描述
MapperFactoryBean实现了FactoryBean接口InitializingBean接口,在对象初始化的时候会调用它的afterPropertiesSet方法,该方法中首先调用了checkDaoConfig()方法,MapperFactoryBean重载的checkDaoConfig()如下:
在这里插入图片描述
Configuration configuration = getSqlSession().getConfiguration();这一句中的getSqlSession()获取的SqlSession
对象就是文章开头的配置文件中配置的。
Configuration 是一个重要的配置类在这里插入图片描述
进入 configuration.addMapper(this.mapperInterface)方法中:
在这里插入图片描述
在configuration内部对Mapper的操作都委托给了mapperRegistry对象,进入它的addMapper(type)方法,这里的参数type就是一个mapper接口的类型(如:com.st.mapper.UserMapper.java):
在这里插入图片描述
knownMappers.put(type, new MapperProxyFactory(type));这一步为我们创建了mapper 的代理工厂类对象,并把它放入了knownMappers这个Map中。MapperProxyFactory这个类我们下面再讲。
MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
parser.parse();
这两句完成了mapper接口对应的xml文件的解析,xml文件中的每一个方法都被解析成了一个MappedStatement对象(代码太长,不再展开),并添加到了configuration对象中:
在这里插入图片描述

对上面的内容的总结:
mapper接口的定义在bean加载阶段会被替换成MapperFactoryBean类型,在spring容器初始化的时候会给我们生成MapperFactoryBean类型的对象,在该对象生成的过程中调用afterPropertiesSet()方法,为我们生成了一个
MapperProxyFactory类型的对象存放于Configuration里的MapperRegistry对象中,同时解析了mapper接口对应的xml文件,把每一个方法解析成一个MappedStatement对象,存放于Configuration里的mappedStatements
这个Map集合中。

下面看一下MapperFactoryBean的getObject()方法,看看mapper代理对象是如何生成的:
在这里插入图片描述
在这里插入图片描述
跟踪代码最后调用的是MapperRegistry.getMapper()方法给我们返回了mapper代理对象。

现在来看一下MapperProxyFactory这个类:
在这里插入图片描述
MapperProxy是被代理的对象,看下这个类:
在这里插入图片描述
在invoke()方法中最终执行的是mapperMethod.execute(sqlSession, args);方法。
来看一下MapperMethod这个类:
在这里插入图片描述
execute()这个方法最终负责执行我们mapper接口中方法,它会判断要执行的方法的类型,然后调用sqlSession对应的方法类型来执行,并放回结果。

  • 6
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值