我不懂MyBatis

mybatis baseexcetor

SpringManagedTransaction 从 DataSourceUtils 取 connect

datasourceutil 从 async transaction util中取connect

有了 transaction 注解 mybatis 如何获取数据库连接

  1. spring TransactionInterceptor 事务切面中,开启事务,会将connect holder 放入 TransactionSynchronizationManager 的thread local中
  2. 当mybatis 需求获取连接时,mybatis 的 SpringManagedTransaction 会从 spring 的 DataSourceUtils 中获取连接。 DataSourceUtils 先从 TransactionSynchronizationManager 取,如果没取到,从DataSource中获取一个,并注册到 TransactionSynchronizationManager 中。

没有 transaction 注解

  1. spring TransactionInterceptor 事务切面中,开启事务,会将connect holder 放入 TransactionSynchronizationManager 的thread local中
  2. 当mybatis 需求获取连接时,mybatis 的 SpringManagedTransaction 会从 spring 的 DataSourceUtils 中获取连接。 DataSourceUtils 从DataSource中获取一个,并注册到 TransactionSynchronizationManager 中。

1. autocommit 什么时候 设置的?

DataSourceTransactionManager dobegin 判断如果 autocommit = true 设置为 false
默认是否为false 看 DruidAbstractDataSource 中 defaultAutoCommit 配置项 是否为 false

1.1 是否 defaultAutoCommit 设置为 false,不加 transaction 注解 数据不会入库?

  1. 最终会调用 SpringManagedTransaction 的 commit方法提交事务
  2. 在SQLsessiontemplate中,SqlSessionInterceptor的invoke中 调用了 method.invoke 执行了 sql之后,会判断是否是 spring 管理的 事务,如果不是 会调sqlsession的commit 提交事务。
  3. spring开启事务会在TransactionSynchronizationManager 加入 sqlsessionfactory:sqlsession的键对值,如果 TransactionSynchronizationManager 中没有,则spring 没有管理事务
  4. SQLsessiontemplate mapperproxy 如何生成的? 和sqlsessiontemplate 关系?
    mapperproxy 在 启动时扫描xml文件生成的。 buildSqlSessionFactory->xmlMapperBuilder.parse()->bindMapperForNamespace()->configuration.addMapper-> add MapperProxyFactory

MapperFactoryBean 为什么要getmapperobject?
1. 依赖注入 factory生成bean
2. 生成MapperProxy spring 认为此类过程是 复杂创建过程,提供 FactoryBean 和复杂逻辑解耦。

MapperProxyFactory 是什么时候 getmapper的?

  1. ClassPathMapperScanner 是通过 注解 @MapperScan 上注解@Import(MapperScannerRegistrar.class) 引入,然后MapperScannerRegistrar.registerBeanDefinitions 中 new ClassPathMapperScanner(register) 生成对象,然后通过 ClassPathMapperScanner.doScan 扫描 Mapper 生成BeanDefinition。 会注册到 register中,beanDefinitionNames 也会新增。

  2. 当beanfactory 实例化controller 时 ,会递归生成依赖的bean ( service -> dao -> mapper ) 。递归入口是 DefaultListableBeanFactory.preInstantiateSingletons方法中的getBean,每次调用 resolveCandidate 获取 依赖的bean时 都会调 beanfactory的getBean 方法,这里的beanFactory是DefaultListableBeanFactory。

  3. 当调 abstractBeanFactory.doGetBean 是Mapper 时。 1) 先从 singletonObjects 中取,如果拿到(拿到的是 factorybean,然后从 factoryBeanObjectCache 获取,没取到的话 就 从factorybean 生成)返回。 2) 没拿到 到后面, 生成 RootBeanDefinition ,递归解决 dependson , 如果单例对象,会先获取 factorybean 对象,然后生成 mapperproxy 。 获取factorybean是从 factoryBeanInstanceCache 中取的, getSingleton 获取到 factorrybbean 对象 (singletonObjects 中会放入 beanName:factoryBean)。 然后 doGetBean 中的 getObjectForBeanInstance 从 factorybean 中获取一个对象(会放入 factoryBeanObjectCache 中)。

  4. 当 context 调 invokeBeanFactoryPostProcessors时。 获取envirment bean 时,会循环 beanDefinitionNames 中 所有bean ,判断 isTypeMatch ,然后从 RootBeanDefinition 中取出 beanclass,是factorybean,但是beanName 不是&开头,所以继续走到 getTypeForFactoryBean 中, 之后又到了 getSingletonFactoryBeanForTypeCheck 中,方法中没有拿到 实例对象,然后就 createBeanInstance ,创建的 MapperFactoryBean 对象,会放到 factoryBeanInstanceCache 中, getTypeForFactoryBean 获取到 mapperfactorybean后,调用 getObjectType 返回 class。 invokeBeanFactoryPostProcessors -> invokeBeanDefinitionRegistryPostProcessors -> postProcessor.postProcessBeanDefinitionRegistry(RefreshAutoConfiguration&RefreshScopeBeanDefinitionEnhancer) -> isApplicable -> registry.getBean(Environment.class); -> getBean -> resolveNamedBean -> getBeanNamesForType -> getBeanNamesForType -> doGetBeanNamesForType -> beanDefinitionNames foreache ( isTypeMatch ) -> getTypeForFactoryBean -> getSingletonFactoryBeanForTypeCheck -> createBeanInstance -> autowireConstructor(这里创建的 mapperfactorybean 没有 sqlsession) 也没有放到cache中。 -> getSingletonFactoryBeanForTypeCheck (factoryBeanInstanceCache 放入 beanName:BeanWrapperImpl->MapperFactoryBean)

  5. getSingleton -> doCreateBean -> populateBean 注入 sqlsessionfactory
    doGetBean ->createBean ->doCreateBean -> populateBean ->
    根据RootBeanDefinition的 propeertyValues 注入MapperFactoryBean 的 sessionfactory。
    ClassPathMapperScanner 扫描mapper生成BeanDefinition 的时候,将addToConfig 将入到 propeertyValues中,如果 ClassPathMapperScanner的 sqlSessionFactoryBeanName 存在,则 将sqlSessionFactory 放入到 propeertyValues ,因为有多数据源,所以这个 sqlSessionFactoryBeanName 是在@MapperScan 注解中配置的。
    ClassPathMapperScanner 是通过 注解 @MapperScan 上注解 @Import(MapperScannerRegistrar.class) 引入,然后 MapperScannerRegistrar.registerBeanDefinitions 中 new ClassPathMapperScanner(register) 生成对象,然后通过 ClassPathMapperScanner.doScan 扫描 Mapper 生成BeanDefinition。

2. 如果有 transaction 注解,调用了没有 transaction 注解的方法。没有注解的方法内部 是否加入到这个事务中?

我不懂MyBatis_第1张图片

3. 连接池初始化的时候 TransactionSynchronizationManager 如何交互的?

你可能感兴趣的:(MyBatiis)