前段时间在优化部门的codegen项目的时候,要将jdbc全部替换成mybatis去执行,有一些个性化的需求单纯的mybatis generator不能满足,于是特意研究了下mybatis,解决在不改造源码的情况下去另类的”扩展“mybatis generator,由于扩展实际上是根据mybatis的套路去进行扩展,所以这里先在第一段介绍一下mybatis-spring的执行原理,第二段会放出例子表明如何进行扩展
一.mybatis-spring执行原理
(1)扫描basePackage,用于将mapper接口扫描成MapperFactoryBean注册到spring
mybatis-spring里面,我们通过MapperScannerConfigurer设置basePackage路径,确定要扫描的Mapper接口,实际上当我们配置了这个basePackage之后,mybatis会扫描这个路径下的所有Mapper接口,并为每个Mapper接口初始化成一个MapperFactoryBean对象,在执行的时候,会通过这个MapperFactoryBean对象的getObject()方法为每个Mapper接口生成一个proxy对象,通过jdk的反射完成,下面来探究一下源码。
从第一张图片可以看到,MapperScannerConfigurer实现了BeanDefinitionRegistryPostProcessor接口,在正常的bean注册完之后,可以进一步做一些自定义的bean操作,我们可以看到第二张图哪里,MapperScannerConfigurer会执行一个scanner.scan方法去读取basePackage下面的mapper接口,scanner里面会调用doScan方法去扫描basePackage下面的Mapper接口成MapperFactoryBean并注册到spring容器里面。
在doScan方法里面,首先会调用findCandidateComponents()方法去将basePackage下面的Mapper类扫面成一个BeanDefinition的集合,然后对这些beanDefinition进行解析成BeanDefinitionHolder,最后通过注册到spring容器里面。获取到这些BeanDefinition之后,再去调用processBeanDefinitions方法将beanDefinition设置beanClass为MapperFactoryBean,在第一次需要使用这个bean的时候spring就会根据beanClass通过反射将对应的bean对象生成出来保存在map里面。