前言:在各大论坛找mybatis和springboot/spring相互关系的文章,不是很多,想自己看下源码分析mybatis怎么把dao解析并注册到spring。
环境准备,org.springframework.boot系列jar,mybatis-spring-boot-starter.jar
1 先看下我们在springboot中配置mybatis的内容,springboot通过mapper-locations: classpath*:com/**/dao/**/*DAO.xml
2 开始我们的分析,我们从MapperScannerRegistrar和ClassPathMapperScanner开始说起把(至于程序如何从启动执行到ClassPathMapperScanner需要自行调试了,步骤太多,说完需要掀开spring一堆堆代码)。它是mybatis-spring.jar的类,功能是扫描步骤1中的dao路径并获取到beanDefinition,即类的定义数据。
3 装载beanDefinition各项数据,包括beanClass,即MapperFactoryBean.class。dao中接口使用的是该类承载代理类,该类实际继承spring的FactoryBean,目的是借助getObject(),放置和存储不同自身的bean。怎么理解?比如需要用到UserService,通常在UserService加上注解@Service是自己注册成bean,而dao下的所有接口实际是代理类MapperProxy生成的动态代理类(下面会说到)。所以需要用spring的FactoryBean方式来实现。
4 dao的接口实际实例化的时机,是在完成bean触发的。在org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)开始看
5 在上一步中可以看到dao的bean执行了doGetObjectFromFactoryBean的逻辑,执行后会进入MapperFactoryBean的实例化了
6 MapperRegistry是什么,MapperRegistry就是dao接口实际代理类生成的地方
7 总结,springboot读取mybatis的xml并解析,之后初始化实际调用mybatis的MapperRegistry,最后通过MapperProxy结合JDK生成动态代理类