1、@ComponentScan basePackages与value: 用于指定包的路径,进行扫描 basePackageClasses: 用于指定某个类的包的路径进行扫描 nameGenerator: bean的名称的生成器 useDefaultFilters: 是否开启对@Component,@Repository,@Service,@Controller的类进行检测 url: https://blog.csdn.net/u012326462/article/details/82765485

2、@ImportResource注解 用于导入 Spring 的 xml 配置文件,让该配置文件中定义的 bean 对象加载到Spring容器中。 参考链接:https://blog.csdn.net/lzb348110175/article/details/105148214

3、 引入依赖

<dependency> <groupId>org.mybatis.spring.boot</groupId>

<artifactId>mybatis-spring-boot-starter</artifactId> </dependency>

在上述BeanFactory的后置处理器中就会读取mybatis-spring-boot-autoconfigure-***.jar包中的spring.factories文件 /org/mybatis/spring/boot/mybatis-spring-boot-autoconfigure/2.1.0/mybatis-spring-boot-autoconfigure-2.1.0.jar!/META-INF/spring.factories org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration

<!-- 通过扫描的模式,扫描目录在mapper目录下,所有的mapper都继承SqlMapper接口的接口, 这样一个bean就可以了-->

@MapperScan和@Mapper都可以,@Mapper每个接口都要写 为什么没有加@MapperScan注解也可以扫描mapper接口 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.hsjry.convert.dal.dao.mapper.**" /> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> </bean>

扫描调用栈 1.org.mybatis.spring.annotation.MapperScannerRegistrar#registerBeanDefinitions(org.springframework.core.annotation.AnnotationAttributes, org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.String)

2.org.mybatis.spring.annotation.MapperScannerRegistrar#registerBeanDefinitions(org.springframework.core.annotation.AnnotationAttributes, org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.String) 声明要注册的对象 BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);

3. 向这个注册中心注册一个新的 bean 定义 要用到BeanDefinitionRegistry org.springframework.beans.factory.support.BeanDefinitionRegistry#registerBeanDefinition

4.org.mybatis.spring.mapper.MapperScannerConfigurer#postProcessBeanDefinitionRegistry

5.org.springframework.context.annotation.ClassPathBeanDefinitionScanner#scan

6.org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan @return 注册的 bean set集 Set<BeanDefinitionHolder>

7.org.mybatis.spring.mapper.ClassPathMapperScanner#doScan

8.ClassPathMapperScanner extends ClassPathBeanDefinitionScanner

9.扫描到mapper接口了 org.mybatis.spring.mapper.ClassPathMapperScanner#processBeanDefinitions

10.ClassPathMapperScanner#processBeanDefinitions // 处理BeanDefinitions // 入参的beanDefinitions是从mapper接口产生的 private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) { GenericBeanDefinition definition; for (BeanDefinitionHolder holder : beanDefinitions) { definition = (GenericBeanDefinition) holder.getBeanDefinition(); // the mapper interface is the original class of the bean // but, the actual class of the bean is MapperFactoryBean // 是为了创建mapperFactoryBean对象时,给mapperInterface赋值 definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName()); // 设置beanClass = mapperFactoryBean.class definition.setBeanClass(this.mapperFactoryBean.getClass()); ....... // 按类型注入,作用是在创建MapperFactoryBean对象时,通过set方法按类型实现装配 definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); } } }

11.org.mybatis.spring.mapper.MapperFactoryBean#getObject public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> 很多都是在spring做扩展

12.org.apache.ibatis.session.SqlSession#getMapper interface

13.org.mybatis.spring.SqlSessionTemplate#getMapper

14.org.apache.ibatis.session.Configuration#getMapper 这个就是SqlSession接口的方法

15.org.apache.ibatis.binding.MapperRegistry#getMapper

16.org.apache.ibatis.binding.MapperProxyFactory#newInstance(org.apache.ibatis.session.SqlSession)

17.org.apache.ibatis.binding.MapperProxyFactory#newInstance(org.apache.ibatis.binding.MapperProxy<T>),在这个方法中,使用JDK动态代理,创建代理对象,该代理对象就是我们Service层的代码中注入的对象 dao层接口。

二.MyBatis的SqlSession是非线程安全的,那Spring的SqlSessionTemplate是怎么解决的这个问题?

1.org.mybatis.spring.SqlSessionTemplate.SqlSessionInterceptor#invoke

2.org.mybatis.spring.SqlSessionUtils#getSqlSession(org.apache.ibatis.session.SqlSessionFactory, org.apache.ibatis.session.ExecutorType, org.springframework.dao.support.PersistenceExceptionTranslator):

public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {

notNull(sessionFactory, NO_SQL_SESSION_FACTORY_SPECIFIED); notNull(executorType, NO_EXECUTOR_TYPE_SPECIFIED);

//从事务同步管理器中取sqlSession

SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);

SqlSession session = sessionHolder(executorType, holder);

//有就返回 if (session != null) { return session; } LOGGER.debug(() -> "Creating a new SqlSession");

//没有就创建 session = sessionFactory.openSession(executorType);

//放到事务同步管理器中 registerSessionHolder(sessionFactory, executorType, exceptionTranslator, session); return session; }

MyBatis 方法调用路由到从 Spring 的事务管理器获得的正确 SqlSession 事务同步管理器可以认为是一个ThreadLocal的map,这样同一个线程在使用SqlSessionTemplate多次对数据库操作的时候,取到的是同一个SqlSession;而不同的线程取到的是不同的SqlSession,所以说SqlSessionTemplate是线程安全的。

三 MyBatis怎么跟Spring声明式事务配合完成的数据库事务内的增删改查操作?

1.设置数据库连接的自动提交为false

2.通过这个数据库连接进行sql语句执行

3.异常回滚或者提交 以上三步中的1和3是Spring声明式事务做的,2是MyBatis做的,它们是怎么配合的呢?其实只需要保证1、2、3这三步中获取到的是同一个数据库连接就好,其实也是通过事务同部管理器这个ThreadLocal的map来实现的 1.org.springframework.transaction.interceptor.TransactionInterceptor#invoke>>

TransactionInterceptor extends TransactionAspectSupport

//存在在threadLocal里面去

org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction 》》

org.springframework.transaction.interceptor.TransactionAspectSupport.TransactionInfo#bindToThread

2.org.mybatis.spring.SqlSessionUtils#getSqlSession(org.apache.ibatis.session.SqlSessionFactory, org.apache.ibatis.session.ExecutorType, org.springframework.dao.support.PersistenceExceptionTranslator)

去spring 管理的事务同步管理器中拿sqlSession 拿不到就拿传进来的SqlSessionFactory去开一个session org.apache.ibatis.session.SqlSessionFactory#openSession(org.apache.ibatis.session.ExecutorType) >>> org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSession(org.apache.ibatis.session.ExecutorType)>>>

org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSessionFromDataSource>>>

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {

Transaction tx = null; try { final Environment environment = configuration.getEnvironment();

//创建的是 就是TransactionFactory实现类org.apache.ibatis.transaction.managed.ManagedTransactionFactory

//从环境配置中拿到的是org.apache.ibatis.transaction.TransactionFactory final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);

// autoCommit是false

//new org.mybatis.spring.transaction.SpringManagedTransaction tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);

final Executor executor = configuration.newExecutor(tx, execType);

return new DefaultSqlSession(configuration, executor, autoCommit);

}

catch (Exception e) { closeTransaction(tx);

// may have fetched a connection so lets call close() throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);

}

finally {

ErrorContext.instance().reset();

}

}

3.org.mybatis.spring.transaction.SpringManagedTransaction#getConnection>>

org.mybatis.spring.transaction.SpringManagedTransaction#openConnection>>

org.springframework.jdbc.datasource.DataSourceUtils#getConnection>>

org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection

四.springboot整合mybatis是怎么做到不用配置mybatis-config.xml的呢?

1.https://mybatis.org/mybatis-3/configuration.html mybatis-config.xml属性参考官网文档

2.用mybatis-config.xml配置文件 org.apache.ibatis.session.SqlSessionFactoryBuilder#build(java.io.Reader, java.lang.String, java.util.Properties)》》

//解析配置文件得到Configuration对象,得到DefaultSqlSessionFactory对象

org.apache.ibatis.session.SqlSessionFactoryBuilder#build(org.apache.ibatis.session.Configuration)》》

org.apache.ibatis.builder.xml.XMLConfigBuilder#parse》》

org.apache.ibatis.builder.xml.XMLConfigBuilder#parseConfiguration 这里的顺序有依赖关系 properties先解析 后面environments,databaseIdProvider都可以用到

properties》settings》typeAliases》plugins》objectFactory》objectWrapperFactory》reflectorFactory》environments》databaseIdProvider》typeHandlers》mappers

3.springboot自动配置 引入依赖 <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> 要使配置生效两种方式

1、@EnableConfigurationProperties(MybatisProperties.class)org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration @EnableConfigurationProperties 注解的作用是:让使用了 @ConfigurationProperties 注解的类生效,并且将该类注入到 IOC 容器中,交由 IOC 容器进行管理

2、使用 @ConfigurationProperties + @Component 注解 用于自定义默认设置的配置对象。如果指定了 {@link #configLocation},则 * 不使用此属性

@NestedConfigurationProperty private Configuration configuration; 表示 {@link ConfigurationProperties} 对象中的字段应该被视为 * 如果它是嵌套类型。此注释与实际绑定 * 进程无关,但它被 {@code spring-boot-configuration-processor} 用作提示 * 字段未绑定为单个值。指定时,*为该字段创建一个嵌套组,并获取其类型。 * <p> * 这对collections and maps没有影响,因为这些类型是自动识别的 前缀是mybatis加@NestedConfigurationProperty 我们就可以表明它是嵌套组了 可以在配置设置这个对象里面的值

mybatis:

  configuration:

    cache-enabled:

@AutoConfigureAfter({ DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class })

public class MybatisAutoConfiguration implements InitializingBean {

提示应该在其他指定的自动配置类之后应用 {@link EnableAutoConfiguration 自动配置} 这个注解表示DataSourceAutoConfiguration MybatisLanguageDriverAutoConfiguration要在MybatisAutoConfiguration 后执行 org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration》》

org.springframework.boot.autoconfigure.jdbc.DataSourceProperties 前缀是spring.datasource 动态代理

spring整合mybatis的debug的步骤:

org.apache.ibatis.session.defaults.DefaultSqlSession@14d6f58f

org.apache.ibatis.session.SqlSession#insert(java.lang.String, java.lang.Object)

org.apache.ibatis.binding.MapperProxy#invoke》》

org.apache.ibatis.binding.MapperMethod#execute》》

org.mybatis.spring.SqlSessionTemplate#insert(java.lang.String, java.lang.Object)》》

org.mybatis.spring.SqlSessionTemplate.SqlSessionInterceptor#invoke》》

org.apache.ibatis.session.defaults.DefaultSqlSession#insert(java.lang.String, java.lang.Object)》》也是通过代理生成的,传统的操作是直接工厂模式new

org.apache.ibatis.session.defaults.DefaultSqlSession#update(java.lang.String, java.lang.Object)》》

org.apache.ibatis.plugin.Plugin#invoke》》

org.apache.ibatis.executor.CachingExecutor#update》》这里面不用创建缓存只有query才需要

org.apache.ibatis.executor.BaseExecutor#update》》

org.apache.ibatis.executor.BaseExecutor#doUpdate》》

org.apache.ibatis.executor.SimpleExecutor#doUpdate》》

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

java.sql.Statement#execute(java.lang.String)

jdbc里内容了

@Override
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.update(stmt);
} finally {
closeStatement(stmt);
}
}

Plugin里的invoke方法

一堆代理

springboot整合mybatis以及mybatis源码分析的更多相关文章

  1. Springboot中mybatis执行逻辑源码分析

    Springboot中mybatis执行逻辑源码分析 在上一篇springboot整合mybatis源码分析已经讲了我们的Mapper接口,userMapper是通过MapperProxy实现的一个动 ...

  2. MyBatis 之 SqlSessionManager 源码分析

    MyBatis 的 4 个基本构成: SqlSessionFactoryBuilder(构造器): 根据配置信息或者代码来生成 SqlSessionFactory(工厂接口) SqlSessionFa ...

  3. MyBatis架构与源码分析<资料收集>

    1.架构与源码分析 :https://www.cnblogs.com/luoxn28/p/6417892.html .https://www.cnblogs.com/wangdaijun/p/5296 ...

  4. springboot Properties加载顺序源码分析

    关于properties: 在spring框架中properties为Environment对象重要组成部分, springboot有如下几种种方式注入(优先级从高到低): 1.命令行 java -j ...

  5. SpringBoot事件监听机制源码分析(上) SpringBoot源码(九)

    SpringBoot中文注释项目Github地址: https://github.com/yuanmabiji/spring-boot-2.1.0.RELEASE 本篇接 SpringApplicat ...

  6. SpringBoot与Mybatis整合方式01(源码分析)

    前言:入职新公司,SpringBoot和Mybatis都被封装了一次,光用而不知道原理实在受不了,于是开始恶补源码,由于刚开始比较浅,存属娱乐,大神勿喷. 就如网上的流传的SpringBoot与Myb ...

  7. Mybatis原理及源码分析

    什么是Mybatis? Mybatis是一个半自动化的持久层框架. Mybatis可以将向PreparedStatement中的输入参数自动进行映射(输入映射),将结果集映射成Java对象(输出映射) ...

  8. mybatis 学习四 源码分析 mybatis如何执行的一条sql

    总体三部分,创建sessionfactory,创建session,执行sql获取结果 1,创建sessionfactory      这里其实主要做的事情就是将xml的所有配置信息转换成一个Confi ...

  9. 学习SpringBoot整合SSM三大框架源码之SpringBoot

    Spring Boot源码剖析 一.Spring Boot 项目的启动入口流程分析 Spring Boot项目的启动入口main线程上有一个@SpringBootApplication( @Confi ...

  10. SpringBoot @ConditionalOnBean、@ConditionalOnMissingBean注解源码分析与示例

    前言: Spring4推出了@Conditional注解,方便程序根据当前环境或者容器情况来动态注入bean,对@Conditional注解不熟悉的朋友可移步至 Spring @Conditional ...

随机推荐

  1. Listen 1音乐播放器

    Listen 1 Listen 1可以搜索和播放来自网易云音乐,QQ音乐,酷狗音乐,酷我音乐,Bilibili,咪咕音乐网站的歌曲,让你的曲库更全面.还支持歌单功能,你可以方便的播放,收藏和创建自己的 ...

  2. 随机森林RF模型超参数的优化:Python实现

      本文介绍基于Python的随机森林(Random Forest,RF)回归代码,以及模型超参数(包括决策树个数与最大深度.最小分离样本数.最小叶子节点样本数.最大分离特征数等)自动优化的代码.   ...

  3. JZOJ 5451.Genocide

    题目 题解 对于 \(m=1\) 这档分 我们可以 \(dp\) 然后斜率优化 具体来说就是 \(f_i = f_j + \frac{(i-j)\times (i-j+1)}{2} + sum[j]- ...

  4. Vulhub 漏洞学习之:Apache HTTPD

    Vulhub 漏洞学习之:Apache HTTPD 目录 Vulhub 漏洞学习之:Apache HTTPD 1 Apache HTTPD 换行解析漏洞(CVE-2017-15715) 1.1 漏洞利 ...

  5. webform项目 aspx页面顶部提示运行时错误(.Net Framwork已下载还是报错)

    找到项目属性页 选择对应的.Net 框架,点击保存,重启一下就好了

  6. left join(一)

    例表aaid adate1 a12 a23 a3 表bbid bdate1 b12 b24 b4 两个表a,b相连接,要取出id相同的字段select * from a inner join b on ...

  7. mybatis动态标签——foreach批量添加和删除

    <!-- [foreach标签] collection:设置要循环的数组或集合 item:用一个字符串表示数组或集合中的每一个数据 separator:设置每次循环的数据之间的分隔符 open: ...

  8. 浏览器控件webBrowser

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  9. 使用clipboard.js复制文字+图片到微信后图片不显示问题处理

    使用clipboard.js复制文字 +图片,粘贴到微信不显示图片,而QQ可以. 解决方案:图片链接使用http,不要使用https. 使用clipboard.js实现复制功能 文字 +图片到微信客户 ...

  10. 04_Linux完全卸载安装Mysql

    1.Linux环境完全卸载mysql相关文件: 完全卸载mysql相关文件:             yum remove mysql mysql-server mysql-libs compat-m ...