思维导图

  • mybatis
    • 1.配置阶段
      • 1.自动装配过程
      • 2.接口扫描过程
      • 3.接口动态代理
      • 4.接口方法映射
    • 2.运行阶段
      • 1.接口方法执行
      • 2.插件链的处理

配置阶段

源码版本:

<!-- pom.xml -->
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot</artifactId>
<version>2.2.1-SNAPSHOT</version>

自动装配过程

基于spring-autoconfig,SPI动态扩展

@startuml
class "MybatisAutoConfiguration" as mac {
  - MybatisProperties properties
  - Interceptor[] interceptors
  - ResourceLoader resourceLoader
  + SqlSessionFactory sqlSessionFactory(DataSource dataSource)
  + SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory)
}
note left of mac
通过spring.factories文件
配置,类似java的SPI机制
主要功能:
1. 声明Bean: SqlSessionFactory
2. 声明Bean: SqlSessionTemplate
3. 创建Configuration
4. 配置Mapper扫描
end note

class "MybatisProperties" as mp{
  - String configLocation
  - String[] mapperLocations
  - String typeAliasesPackage
  - String typeHandlersPackage
  - boolean checkConfigLocation
  - ExecutorType executorType
  - Properties configurationProperties
  - Configuration configuration
  + Resource[] resolveMapperLocations()
}
note top of mp
yml配置文件中前缀为`mybatis`的配置项
声明config文件位置,还有yml中的配置
end note

class "AutoConfiguredMapperScannerRegistrar" as msr <<ImportBeanDefinitionRegistrar>> {
  - BeanFactory beanFactory
  + void registerBeanDefinitions(AnnotationMetadata, BeanDefinitionRegistry)
}
note left of msr
实现ImportBeanDefinitionRegistrar接口
注入MapperScannerConfigurer实例,用于
配置扫描Mapper
end note

interface "BeanDefinitionRegistry" as bdr {
  ...
  + void registerBeanDefinition(String beanName, BeanDefinition)
}

interface "BeanDefinitionRegistryPostProcessor" as bdrpp <<BeanFactoryPostProcessor>>{
  + void postProcessBeanFactory(ConfigurableListableBeanFactory)
  + void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry)
}
class "DefaultListableBeanFactory" as dlbf {
  - Map<String, BeanDefinition> beanDefinitionMap
  - volatile List<String> beanDefinitionNames
}
class "ClassPathBeanDefinitionScanner" as cpbds{
  - BeanDefinitionRegistry registry
  + int scan(String... basePackages)
  # Set<BeanDefinitionHolder> doScan(String... basePackages)
}

class "MapperScannerConfigurer" as msc <<BeanDefinitionRegistryPostProcessor>>{
  - Class<? extends Annotation> annotationClass
  - String basePackage
  - 其他属性..
  + void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry)
}

class "ClassPathMapperScanner" as cpms{
  - Class<? extends Annotation> annotationClass
  - Class<? extends MapperFactoryBean> mapperFactoryBeanClass = MapperFactoryBean.class
  + void registerFilters()
  + Set<BeanDefinitionHolder> doScan(String... basePackages)
  - void processBeanDefinitions(Set<BeanDefinitionHolder>)
}
note left of cpms::registerFilters
设置过滤,扫描Mapper注解
this.addIncludeFilter(new AnnotationTypeFilter(this.annotationClass));
end note
note left of cpms::processBeanDefinitions
核心处理方法,将扫描到的类设置为MapperFactoryBean.class
definition.setBeanClass(this.mapperFactoryBeanClass)
设置依赖sqlSessionFactory等
end note

interface "FactoryBean<T>" as fb {
  + String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType"
  + T getObject()
  + Class<?> getObjectType()
  + boolean isSingleton()
}
note left of fb::getObject
最终生成实例代理类
end note

class "DaoSupport" as ds <InitializingBean> {
  + void afterPropertiesSet()
  + void checkDaoConfig()
  + void initeDao()
}
note right of ds::afterPropertiesSet
调用checkDaoConfig,最终通
过Configuration.addMapper
添加mapper
end note

class "SqlSessionDaoSupport" as ssds extends ds {
  + void checkDaoConfig()
}
class "MapperFactoryBean" as mfb extends ssds implements fb {
  - boolean addToConfig = true
  - Class<T> mapperInterface
  - SqlSessionTemplate sqlSessionTemplate
  + void checkDaoConfig()
  + T getObject()
}
note left of mfb::mapperInterface
业务代码定义的类,注解Mapper修饰
end note
note right of mfb::sqlSessionTemplate
通过模板获取到之前生成的configuration
配置
end note
note right of mfb::checkDaoConfig
重写,调用Configuration.addMapper添加
end note
note left of mfb::getObject
通过Configuration生成过去代理类
end note

class "Configuration" as cfg{
  - MapperRegistry mapperRegistry
  + bool hasMapper(Class)
  + void addMapper(Class)
}
note left of cfg
MybatisProperties声明的文件位置,
MybatisAutoConfigurtion创建的配置
end note

class "MapperRegistry" as mr {
  - Map<Class<?>, MapperProxyFactory<?>> knownMappers
  + boolean hasMapper(Class<T>)
  + void addMapper(Class<T>)
  + void getMapper(Class<T>, SqlSession)
}
note left of mr
注册Mapper,和生成Mapper代理工厂,
通过Mapper代理工厂最终生成代理类提供给
Spring容器
end note

class "MapperProxyFactory<T>" as mpf{
  - Class mapperInterface
  - Map<Method, MapperMethodInvoker> methodCache
  + T newInstance(SqlSession)
}
class "MapperProxy" as mproxy <<InvocationHandler>> {
  - SqlSession sqlSession
  - Class<T> mapperInterface
  - Map<Method, MapperProxy.MapperMethodInvoker> methodCache
}
note left of mproxy
最终注入容器的JDK代理类,
解析定义的Mapper接口方法并缓存句柄
运行时执行
end note

mac::properties <- mp
mac <-- msr : @Import导入配置
msr::registerBeanDefinitions <. bdr
bdr <|.. dlbf: 注册信息保存在Map中
msr .[hidden]. bdrpp
msr <--- msc
bdrpp <|.. msc
msc <-- cpms
bdr <--- cpbds
cpbds <|.. cpms
cpms <--- mfb
fb .[hidden] (cpms, mfb)
mfb <-- cfg
cfg <-- mr
mr <-- mpf
mpf <-- mproxy

@enduml

运行阶段

Mybatis 接口方法执行流程

源码版本:

JDK8和JDK9之后稍有不同,之后版本方法通过方法句柄实现,功能一致,没有太大区别

@startuml
annotation Service
class XXService {
  - mapper:IMapper
}
interface IMapper {
    + Object doSomething()
}
class MapperProxy <<InvocationHandler>> {
  - SqlSession sqlSession
  - Class<T> mapperInterface
  - Map<Method, MapperMethod> methodCache
}
class MapperMethod {
  - SqlCommand command
  - MethodSignature method
  + Object execute(SqlSession sqlSession, Object[] args)
  - Object rowCountResult(int rowCount)
}
class SqlCommand{
  - String name
  - SqlCommandType type
}
class MethodSignature {
  - boolean returnsMany
  - boolean returnsMap
  - boolean returnsVoid
  - Class<?> returnType
  - String mapKey
  - Integer resultHandlerIndex
  - Integer rowBoundsIndex
  - SortedMap<Integer, String> params
  - boolean hasNamedParameters
  + Object convertArgsToSqlCommandParam(Object[] args)
  + RowBounds extractRowBounds(Object[] args)
  + ResultHandler extractResultHandler(Object[] args)
}
interface SqlSession {
  - void select(...)
  - List selectList(...)
}
class DefaultSqlSession {
  - Executor executor
}
interface Executor {
  + List query(MappedStatement var1, Object var2, RowBounds var3, ResultHandler var4)
  + List query(...)
}
abstract class BaseExecutor implements Executor {
  - PerpetualCache localCache
  - List queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
  # abstract List doQuery(MappedStatement var1, Object var2, RowBounds var3, ResultHandler var4, BoundSql var5)
}
class SimpleExecutor extends BaseExecutor{
  + List doQuery(MappedStatement var1, Object var2, RowBounds var3, ResultHandler var4, BoundSql var5)
}
interface StatementHandler {
  + List query(Statement var1, ResultHandler var2)
}
class RoutingStatementHandler {
  - StatementHandler delegate
}
class Configuration {
  - InterceptorChain interceptorChain
  + StatementHandler newStatementHandler(...)
}
class InterceptorChain{
  - List<Interceptor> interceptors
  + Object pluginAll(Object target)
  + void addInterceptor(Interceptor interceptor)
}
interface Interceptor {
  + Object intercept(Invocation var1) throws Throwable
  + Object plugin(Object var1)
  + void setProperties(Properties var1)
}
class Plugin <<InvocationHandler>> {
  - Object target
  - Intercepor interceptor
  - Map<Class<?>, Set<Method>> signatureMap
  + Object wrap(Object target, Interceptor interceptor)
}
interface ResultHandler {
  + List handleResultSets(Statement var1)
}
interface PreparedStatement {
  + void execute()
}

XXService .> Service
XXService <-- IMapper : 成员变量
XXService <-- MapperProxy : spring容器注入实例
MapperProxy -left- IMapper : JDK动态代理
MapperProxy o-- MapperMethod : Map缓存
MapperMethod -left> SqlCommand
MapperMethod -> MethodSignature
MapperMethod <.. SqlSession : execute参数调用
SqlSession <|-- DefaultSqlSession
DefaultSqlSession -> Executor
SimpleExecutor <.. StatementHandler : Plugin层层代理过后的实例
StatementHandler <|--- RoutingStatementHandler
StatementHandler <|--- PreparedStatementHandler
Configuration <.... RoutingStatementHandler : 构建并应用插件链
Configuration .> SimpleExecutor
Configuration <-- InterceptorChain
InterceptorChain o.. Interceptor: pluginAll层层包装target(JDK动态代理)
Interceptor <.. Plugin : Plugin.warp 包装成代理类
Interceptor --> Plugin
InterceptorChain .[hidden] StatementHandler
Plugin = RoutingStatementHandler : JDK动态代理
RoutingStatementHandler -- PreparedStatementHandler: 静态代理
PreparedStatement .> PreparedStatementHandler
PreparedStatementHandler <. ResultHandler
@enduml