mybatis源码分析之初始化过程

从org.mybatis.spring.annotation.MapperScan注解开始。

这个注解指定了java接口basePackages和sqlSessionTemplateRef

SqlSessionTemplate关联着SqlSessionFactory,SqlSessionFactory关联着DataSource和MapperLocations。

 

如果没有配置对应的bean,org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration会自动装配。

如果没有指定mapper文件路径,默认会去加载接口包名相对应的路径下的xml,最终会在org.apache.ibatis.session.Configuration#addMappedStatement这里添加MappendStatement。

入口为:org.mybatis.spring.mapper.MapperFactoryBean#checkDaoConfig

 org.apache.ibatis.binding.MapperRegistry#addMapper

 org.apache.ibatis.builder.annotation.MapperAnnotationBuilder#loadXmlResource

 MapperScan通常配置如下:

 

从上面的关系描述看,MapperScan是桥梁,联动着业务代码接口的调用到sql的关联执行。

 核心也是在@Import:

org.mybatis.spring.annotation.MapperScannerRegistrar

 ImportBeanDefinitionRegistrar这个接口详细见@Import分析那篇博文,主旨意思就是把BeanDefinitionRegistry开放给开发人员自由注册beanDefinition。

看下接口方法的具体实现,解析MapperScan注解配置信息,并通过org.mybatis.spring.mapper.ClassPathMapperScanner#ClassPathMapperScanner扫描所有接口。

核心为内部私有方法org.mybatis.spring.annotation.MapperScannerRegistrar#registerBeanDefinitions(org.springframework.core.annotation.AnnotationAttributes, org.springframework.beans.factory.support.BeanDefinitionRegistry)主要还是实例化ClassPathMapperScanner并做一些配置。

重点看下这两行,第一行注册includeFilters,这在父类里面很重要,父类先根据basePackages扫描到所有Resource(包括class和interface),然后根据includeFilters决定是否将为该resource生成beanDefinition,

代码在org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#scanCandidateComponents:

 org.mybatis.spring.mapper.ClassPathMapperScanner#registerFilters如下:

 

 org.mybatis.spring.mapper.ClassPathMapperScanner#doScan如下:

 org.mybatis.spring.mapper.ClassPathMapperScanner#processBeanDefinitions看下重点的几行:

从注释可以得知,修改beanClass为org.mybatis.spring.mapper.MapperFactoryBean,并将原有beanClass设置为构造方法参数mapperInterface

 

 下面看下org.mybatis.spring.mapper.MapperFactoryBean:

 这两个应该很熟悉了,MapperFactoryBean首先是一个factoryBean,getObject内容如下:

 这里的mapperInterface就是刚刚修改beanDefinition传入的最原始接口类,sqlSessionTemplate对应注解的配置。

 以上内容可以解答接口自动配置了,剩下的就看下getMapper方法:

org.apache.ibatis.session.Configuration#getMapper =》org.apache.ibatis.binding.MapperRegistry#getMapper =》 org.apache.ibatis.binding.MapperProxyFactory#newInstance(org.apache.ibatis.session.SqlSession)

=》org.apache.ibatis.binding.MapperProxyFactory#newInstance(org.apache.ibatis.binding.MapperProxy<T>)

 最终是通过jdk接口代理的方式为原始mapperInterface接口创建代理类,重点逻辑在InvocationHandler ----- org.apache.ibatis.binding.MapperProxy#MapperProxy

构造方法解析得到SqlCommand:

 

 

 以INSERT为例深入看下:

org.mybatis.spring.SqlSessionTemplate#insert(java.lang.String, java.lang.Object) =》 org.apache.ibatis.session.defaults.DefaultSqlSession#insert(java.lang.String, java.lang.Object) =》 org.apache.ibatis.session.defaults.DefaultSqlSession#update(java.lang.String, java.lang.Object)

org.apache.ibatis.executor.BaseExecutor#update

 org.apache.ibatis.executor.SimpleExecutor#doUpdate

重点看下圈中的两个handler,下面截图的内容应该就很熟悉了,都是jdbc的内容就不细讲了。

org.apache.ibatis.executor.statement.PreparedStatementHandler#update

 

 org.apache.ibatis.executor.statement.SimpleStatementHandler#update

 

posted on 2021-06-15 18:00  砌码匠人  阅读(67)  评论(0编辑  收藏  举报

导航