Mybatics执行过程

mybatics mapper的注入过程

  • 在使用mybatics时,通过MapperScan注解 import registrar MapperScannerRegistrar
  • 在MapperScannerRegistrar中会对 ClassPathMapperScanner进行初始化,如setMapperFactoryBean,setSqlSessionTemplateBeanName,setSqlSessionFactoryBeanName等;然后调用ClassPathMapperScanner.doScan方法
  • 在doScan方法中会扫描所有的Mapper,并通过MapperFactoryBean生成对应的代理类,然后将该类注册到spring bean factory中,在初始化BeanDefinition时,会通过RuntimeBeanReference添加需要的属性,如sqlSessionTemplate,sqlSessionFactory等,而sqlSessionTemplate,sqlSessionFactory是在MybatisAutoConfiguration中注入到BeanFactory中的。
  • MapperFactoryBean继承了SqlSessionDaoSupport,在spring 创建MapperFactoryBean会通过sqlSessionTemplate或sqlSessionFactory生成sqlSession
  • 在执行某个mapper时,执行的是动态代理类,代理类为MapperProxy,该类的getObject()方法通过sqlSession.configuration获取对应的mapper
  • 在org.apache.ibatis.session.Configuration.getMapper()方法中调用MapperRegistry.getMapper()
  • MapperRegistry.getMapper()通过MapperProxyFactory生成对应的代理类,代理类的handler为MapperProxy
  • 将该代理类通过factorybean及beandefinition注入到spring 容器中

mapper的执行过程

创建DefaultSqlSession

  • 在执行某mapper时,实际执行的是代理类MapperProxy的invoke方法
  • 在该类的invoke方法中会调用MapperMethod.execute()方法,在该execute方法中,会根据方法类型(如 select/update/delete等,是由mapper xml标签决定的),执行不同的方法
  • 如select方法,接下来会调用SqlSessionTemplate.selectList()方法,然后调用内部类的SqlSessionInterceptor.invoke()方法,此处是动态代理
  • 在该invoke()方法中,通过导入的静态方法执行SqlSessionUtils.getSqlSession(),在该方法中会调用DefaultSqlSessionFactory.openSession(ExecutorType execType)方法
  • 在openSessionFromDataSource()方法中,会开启事务,并且通过事务及ExecutorType创建Executor,如 SimpleExecutor、ReuseExecutor、CachingExecutor、BatchExecutor
  • interceptorChain.pluginAll(executor)以executor为入参调用所有的Interceptor的plugin()方法
  • 创建DefaultSqlSession

执行拦截器及Query

  • 通过该sqlSession调用其 selectList(String statement, Object parameter)方法,最终会调用executor.query方法
  • 该query方法会进入到代理类中,该代理类会执行Executor的mybatics对应的拦截器
  • 在拦截器中,当执行invocation.proceed()时,继续执行Executor.query方法
  • 在该方法中会进行一些Cache的判断及处理,然后调用queryFromDatabase方法,然后调用doQuery方法
  • 在SimpleExecutor.doQuery方法中会调用prepareStatement方法

获取Connection的过程

  • SimpleExecutor.prepareStatement中调用父类 BaseExecutor.getConnection()
  • BaseExecutor.getConnection()中调用SpringManagedTransaction.getConnection(),然后执行当前类中的openConnection()
  • 在方法openConnection()中调用DataSourceUtils.getConnection(this.dataSource)
  • 在类DataSourceUtils中最终会通过fetchConnection(dataSource)调用AbstractRoutingDataSource.getConnection()
  • 在通过DataSource获取Connection时,实际调用的是AbstractRoutingDataSource.getConnection()方法
  • DynamicDataSource继承于AbstractRoutingDataSource
  • AbstractRoutingDataSource间接实现了接口DataSource
  • 在AbstractRoutingDataSource.getConnection()方法中会调用内部方法determineTargetDataSource()获取DataSource,然后调用该DataSource.getConnection()方法(此处采用装饰模式)
  • 在方法determineTargetDataSource()中,会调用该抽象类的抽象方法determineCurrentLookupKey(),然后从targetDataSource中获取该key对应的DataSource(此处使用模板模式)
  • 通过上述过程获取到的Connection生成Statement

查询

  • 然后调用StatementHandler.query方法
  • 之后会进行查询数据库,并封装响应数据