1.jar包版本:mybatis-plus-boot-starter 3.5.3.1
还是从MybatisPlusAutoConfiguration开始说。
创建MybatisSqlSessionFactoryBean时在applyConfiguration方法中为factoory对象configuration属性设置了MybatisConfiguration类型的对象。
![](https://i-blog.csdnimg.cn/blog_migrate/036b640396cba4f6948f3f57a567fcdf.png)
在创建对象SqlSessionTemplate时将sqlSessionFactory作为构造参数传入了SqlSessionTemplate对象。
![](https://i-blog.csdnimg.cn/blog_migrate/13fc4b5b573e56e2094140179ba0f46c.png)
在定义MapperScannerRegistrarNotFoundConfiguration类时使用了@import注解导入了AutoConfiguredMapperScannerRegistrar类,这个类实现了ImportBeanDefinitionRegistrar接口,会调用接口的registerBeanDefinitions方法设置bean定义。
![](https://i-blog.csdnimg.cn/blog_migrate/2412444bd2203a0b4d7501fdd6049c87.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c6d73aff8e84ddd4196cd0d3fb6164c0.png)
这里引入了MapperScannerConfigurer的bean定义。这个类实现了BeanDefinitionRegistryPostProcessor接口,BeanDefinitionRegistryPostProcessor在AbstractApplicationContext的refresh方法中会被调用。
![](https://i-blog.csdnimg.cn/blog_migrate/d0ffea6d82106700078afde4c6970d8b.png)
继续跟MapperScannerConfigurer的postProcessBeanDefinitionRegistry方法会调用ClassPathMapperScanner的processBeanDefinitions方法。
![](https://i-blog.csdnimg.cn/blog_migrate/8d6024eb188961d9f77d3dcfa8d8cefc.png)
在processBeanDefinitions方法中对bean定义设置了beanclass为MapperFactoryBean,mapperInterface为业务的Mapper接口。在创建bean时便会创建一个MapperFactoryBean对象。
![](https://i-blog.csdnimg.cn/blog_migrate/6915ad0d9bff63a2918569993ef3d694.png)
MapperFactoryBean继承了SqlSessionDaoSupport类,该类实现了InitializingBean接口,所以在创建MapperFactoryBean对象调用init方法之前会调用afterPropertiesSet方法,该方法会调用到checkDaoConfig方法将mapper接口放入MybatisConfiguration的MybatisMapperRegistry对象的knownMappers属性中。
![](https://i-blog.csdnimg.cn/blog_migrate/598a0ce6f5ac44e4109b895c6ec8cb70.png)
在创建业务mapper(我们这里是TestMapper)的bean对象时最终创建的是MybatisMapperProxyFactory对象。跟踪MybatisMapperAnnotationBuilder的parse方法可以发现BaseMaper中方法的生成方式。一直跟到injectMappedStatement方法的调用。
![](https://i-blog.csdnimg.cn/blog_migrate/dc9c6ae10bbcffa2e762228b9a36fab1.png)
这些类都是AbstractMethod的子类,这类的名称是不是与BaseMapper中的方法一样。以DeleteById这个类为例,看injectMappedStatement的第二句代码SqlMethod sqlMethod = SqlMethod.LOGIC_DELETE_BY_ID,SqlMethod.LOGIC_DELETE_BY_ID的内容为
![](https://i-blog.csdnimg.cn/blog_migrate/3604ee4df5ed685efde9173b260d331a.png)
是不是sql语句就出来了。
接着先前的问题看SqlSessionFactory的创建。
![](https://i-blog.csdnimg.cn/blog_migrate/54bfd9c559a7e3e60bae73176831df2a.png)
这里的属性SqlSessionFactory在MapperFactoryBean类以及父类中不存在,那他是怎么来的?
那就跟unsatisfiedNonSimpleProperies这个方法,在这个方法中调用getCachedIntrospectionResults方法,在这个放方法中又调用CachedIntrospectionResults.forClass(getWrappedClass())。一路跟到Introspector的getTargetPropertyInfo方法。
![](https://i-blog.csdnimg.cn/blog_migrate/7129f4606905a8347b3b2e63aec020b4.png)
在这个方法中会解析set/get方法,拿到SqlSessionFactory属性。
回到MybatisMapperProxyFactory类上来,这个类的newInstance创建的是一个代理执行的是methodCache的MapperMethodInvoker中的inoke方法。
![](https://i-blog.csdnimg.cn/blog_migrate/ecc66a5902ae8f7aec411495a2898a9f.png)
PlainMethodInvoker的实现类PlainMethodInvoker代用MybatisMapperMethod的execute方法。
![](https://i-blog.csdnimg.cn/blog_migrate/6142b26d8d7734c301f991d8cd33b722.png)
下面就是查询的逻辑了,就可以结合上一篇分页插件实现联系起来了,整个流程就走通了。
总结流程:
修改mapper定义中的beanclass属性为MapperFactoryBean,创建MapperFactoryBean时会调用InitializingBean的afterPropertiesSet方法,在该方法中调用addMapper设置MybatisMapperRegistry对象的knownMappers属性,保存接口与MybatisMapperProxyFactory的映射关系。
创建mapper时会代用MybatisFactoryBean的getObject,然后调用MybatisMapperRegistry的getMapper接口从knownMappers获取到MybatisMapperProxyFactory,通过MybatisMapperProxyFactory.newInstance创建代理对象MybatisMapperProxy。MybatisMapperProxy调用MapperMethodInvoker。