Mybatis-Plus的BaseMapper代理类的生成过程
前言
前面一篇介绍了BaseMapper的作用,只要自定义接口实现了BaseMapper,就可以使用单表CRUD,而不需要进行xml或sql的编写,怎么生成对应的sql,可以参考上一篇文章。
在介绍如何利用BaseMapper生成的sql进行查询之前,本篇先来了解下BaseMapper的实现接口是如何加载到spring容器中的。
在使用MyBatis作为数据访问层框架的时候,通常需要将Mapper接口扫描并注册到Spring容器中,然后在业务逻辑代码中使用@Autowired或@Resource注解注入Mapper接口,从而实现对数据访问层的调用。
使用mapper示例,如下所示:
@Resource
private OrderMapper orderMapper;
...
{
...
orderMapper.selectList(new QueryWrapper<>());
}
原理
demo项目传送门>
1、首先是在启动类上加注解@MapperScan(“top.xudj.mp.mapper”)扫码mapper,这些mapper接口都实现了BaseMapper,如下:
public interface UserMapper extends BaseMapper<User> {
}
2、@MapperScan注解的定义上使用了@Import注解,将MapperScannerRegistrar类导入到当前的配置类中。MapperScannerRegistrar实现了ImportBeanDefinitionRegistrar接口,用于动态向Spring容器中注入MapperScannerConfigurer,从而实现Mapper接口的自动扫描和注册。
3、启动项目,进入到了MapperScannerRegistrar类,MapperScannerRegistrar 实现了接口ImportBeanDefinitionRegistrar,
重写了registerBeanDefinitions方法,如下图所示:
在最后一行,可以看到进行beanDefinition的注册,这个beanDifinition就是MapperScannerConfigurer。
4、接着看MapperScannerConfigurer。
在其它beanDefinition都加载了后,还没有实例化前,会调用postProcessBeanDefinitionRegistry方法,因为MapperScannerConfigurer实现了BeanDefinitionRegistryPostProcessor接口,如下图所示
在postProcessBeanDefinitionRegistry方法中 扫描mapper接口所在包,完成mapper实例化。
5、扫描类是ClassPathMapperScanner,实现了spring的ClassPathBeanDefinitionScanner类,进入到spring的ClassPathBeanDefinitionScanner类中完成扫描,basePackage便是@MapperScan注解上的路径。
6、在spring的scan扫码后,进行了beanDefinition的注册。
之后回到ClassPathMapperScanner类,在调用spring的doScan之后,如下图所示,会进行后续的处理,往下看。
7、继续看ClassPathMapperScanner的processBeanDefinitions方法(第6步圈出的方法),核心的代码如下图所示:
修改BeanDefinition的类,beanClass修改为:class org.mybatis.spring.mapper.MapperFactoryBean。
这里可以看到,以mapper接口为beanDefinition的beanClass被修改了。spring实例化的时候便会按这个类来创建实例。
8、在bean实例化的时候,再进一步通过实例化对应的mapper,对应的类是MapperFactoryBean,会调用其getObject方法。
MapperFactoryBean实现了接口FactoryBean,其用于进行复杂bean的创建所用,会调用对应的getObject方法。
9、继续往下看调用,进入到sqlSessionTemplate的getMapper方法
截图可以看到,configuration不是mybatis的,而是Mp的MybatisConfiguration类。
10、继续,进入到mapper的实例化类
11、进入到mapper代理类实现工厂类MybatisMapperProxyFactory,通过Proxy完成实例化mapper的代理类MybatisMapperProxy创建。
总结
至此,MybatisMapperProxy
com.baomidou.mybatisplus.core.override.MybatisMapperProxy implements InvocationHandler 使用了jdk的动态代理类