MyBatis源码学习笔记

mybatis学习 关注点:Mapper绑定、Executor、Cache、Plugin

一、Mybatis初始化

DataSource dataSource = BlogDataSourceFactory.getBlogDataSource();
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment =  new Environment("development", transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);
configuration.addMapper(BlogMapper.class);
//初始化
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);

构建 SqlSessionFactory的主要过程:

  1. 初始化Configuration ,包括mapperRegistry,typeAliasRegistry,typeHandlerRegistry
  2. 注册:解析mapper xml, 把其中的节点信息和Mapper类的方法一一对应,每个方法对应生成一个 MappedStatement(包括SQL类型、参数、结果映射、缓存等信息配置),并添加到 Configuration 中;
  3. 绑定:根据 Mapper xml 中的 namespace, 为每个mapperInterface创建对应的MapperProxyFactory,用于 Mapper 代理对象的生成,但此时并没有生成代理类,而是在后续调用sqlSession.getMapper(Class<T> type);时通过该工厂创建代理实例

mapper绑定:

mapper绑定

二、Executor组件

数据库操作执行器,输入为数据库操作上下文、SQL参数、结果解析器,输出为执行结果,另外也可以是事务commit和rollback。

执行流程:

  1. 从DataSource获取Connection
  2. 初始化statement,用于执行SQL并返回结果集 connection.prepareStatement() or connection.createStatement(),设置timeout、fetchSize参数
  3. 参数预编译
  4. 执行SQL并返回结果集
  5. 结果集映射成对象后返回

三、插件机制

目的:通过插件配置让用户可以在执行SQL、参数设置、结果解析时进行拦截,如进行监控等。

允许拦截的过程:

  • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  • ParameterHandler (getParameterObject, setParameters)
  • ResultSetHandler (handleResultSets, handleOutputParameters)
  • StatementHandler (prepare, parameterize, batch, update, query)

插件初始化

  1. 初始化Configuration的过程中解析xml配置的plugins节点
  2. 生成拦截器Interceptor实例,注册到拦截器chain中

执行机制

以PageHelper拦截器为例

  1. 在获取SqlSession的过程中,生成Executor实例时将拦截器chain中的拦截器对其进行插桩,即进行动态代理,这个代理的过程是嵌套形成责任链
  2. 当然并不是每个拦截器都会拦截Executor,拦截器通过@Intercepts注解指定需要拦截的类、方法信息,插桩时由mybatis的Plugin类进行解析判断是否需要生成代理。
  3. 执行Executor的拦截机制与动态代理拦截机制一致,需要注意的是有可能有多层代理嵌套

四、mybatis-spring

使用Mybatis遇到问题

  1. sqlSessionFactory手动new实例,不被Spring管理
  2. 使用比较麻烦,需要每次生成sqlSession,Mapper实例,如下
SqlSession session = sqlSessionFactory.openSession();
try {
  BlogMapper mapper = session.getMapper(BlogMapper.class);
  Blog blog = mapper.selectBlog(101);
} finally {
  session.close();
}
  1. 对象不复用,对性能不友好

所以,通过依赖注入框架来管理对象的生命周期,mybatis-spring即进行两者之间的桥接。

功能:

  • MapperScannerConfigurer 扫描配置basePackage指定的mapper,生成对应的BeanDefinition和MapperFactoryBean,MapperFactoryBean用于维护sqlSession并获取mapperInterface的代理实现类,最终使得mapperInterface可以被自动注入。
  • 实现线程安全的sqlSesion,管理其生命周期,解决每次执行数据库操作时先手动openSession再close的操作,而mybatis defaultSqlSesion非线程安全,使用时为方法级别作用域,
  • 将SqlSessionFactory,Mapper的实例都纳入Spring容器管理

mapper注入原理

MapperScannerConfigurer实现了BeanDefinitionRegistryPostProcessor,后者是Spring IoC的扩展点之一,允许beanDefinition的自定义后置操作,如注册新的自定义beanDefinition,可用于动态注册beandefinition,从而动态注册bean。

MapperScannerConfigurer具体code(已简化):

@Override
  public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
	//扫描该package下的class
    scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage);
  }
  
  //**ClassPathMapperScanner**.doScan
  @Override
  public Set<BeanDefinitionHolder> doScan(String... basePackages) {
  	//扫描class,新增BeanDefinition,并注册到BeanDefinitionRegistry
    Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
	
	for (BeanDefinitionHolder holder : beanDefinitions) {
	// 设置beanClass,最终获得的bean将是MapperFactoryBean.getObject方法返回的对象
      // the mapper interface is the original class of the bean
      // but, the actual class of the bean is MapperFactoryBean
      definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName()); 
      definition.setBeanClass(this.mapperFactoryBean.getClass());
	
	definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
       
    }
	
    return beanDefinitions;
  }
  
  **MapperFactoryBean**实现FactoryBean<T>
  @Override
  public T getObject() throws Exception {
    return getSqlSession().getMapper(this.mapperInterface);
  }

参考

http://objcoding.com/2018/06/01/mybatis-mapper/

转载于:https://my.oschina.net/hebaodan/blog/1936208

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值