TSharding源码阅读
需要的背景知识:Spring 和Mybatis 实现原理和源码, javaassist字节码增强的使用, java及设计模式的使用
1 读取解析数据库配置文件
DataSourceScanner实现了Spring的BeanDefinitionRegistryPostProcessor和ApplicationContextAware接口。
BeanDefinitionRegistryPostProcessor 允许定义bean
ApplicationContextAware 可以获取Spring上下文。
代码流程:getDataSources解析读取数据库配置文件生成dataSourcesMapping( Map<String, Map<DataSourceType, DataSource>>),registerDataSources 遍历dataSourcesMapping生成DataSourceFactoryBean(名字格式trade0005SlaveDataSource)并注入到SpringBean工厂。继续遍历解析数据源,封装成Map<String, ReadWriteSplittingDataSource> ,如果有可写数据源则创建事务管理器(名字格式trade0005TransactionManager),注册到SpringBean工厂。如果可写数据源不存在,注册一个空transactionManager。如果只有一个可写数据源,则添加别名,兼容默认情况。解析完数据源后,向Spring注册dataSourceLookup,其实就是把数据源map保存起来。
2 MapperScannerWithSharding
Tsharding MybatisMapper的扫描类,负责将Mapper接口与对应的xml配置文件整合,绑定设定的数据源,注入到Spring Context中。
实现了BeanFactoryPostProcessor, InitializingBean 接口 。BeanFactoryPostProcessor可以修改BEAN的配置信息
代码流程:
获取1步中注册的dataSourceLookup。
initSqlSessionFactories。第一次SqlSessionFactoryBean.setMapperLocations.setDataSource.setTypeAliasesPackage(mapper位置,数据源,实体类),实例化SqlSessionFactoryBean,单例注册到bean工厂(名字格式为trade0001)。后续,从第一次的sessionFactoryBean.getObject()获取一个SqlSessionFactory,
然后从SqlSessionFactory获取configuration,就是Resource,
从Resource获取SqlSessionFactory返回Configuration,从Configuration获取mappedStatements( Map<String, MappedStatement>),
然后为了后续的元数据复用再 Map<String, MappedStatement> 放回Configuration.最后使用SqlSessionFactoryLookup 把所有sqlSessionFactories保存起来,放入MapperScannerWithSharding
ClassPathScanHandler:扫描所有配置文件下所以java类,
新生成mapper,如果这些类是mapper类,新生成,并单例注册到bean工厂
private Object newMapper(final Class<?> clazz) {
final Invoker invoker = new TShardingRoutingInvokeFactory(sqlSessionFactoryLookup).newInvoker(clazz);
//动态代理 invoker
return Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, final Method method, final Object[] args) throws Throwable {
return invoker.invoke(new DefaultInvocation(method, args));
}
});
}
TShardingRoutingInvokeFactory 类:
判断mapperInterface 是否带注解,如果注解为TShardingRoutingHandler,使用Sharding数据源,走分表分库。
不带注解,正常的使用配置的数据源。 走分表分库分支:返回内部类Invoker
3:MapperShardingInitializer 增强Mapper处理总入口:Mapper被mybatis初始化后,在这里做进一步的处理和增强、
http://www.cnblogs.com/clds/p/5966815.html
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Map<String, SqlSessionFactory> sqlSessionFactories = applicationContext.getBeansOfType(SqlSessionFactory.class);
if (sqlSessionFactories.isEmpty()) {
return;
}
MapperHelperForSharding mapperHelperForSharding = new MapperHelperForSharding();
List<SqlSession> sqlSessions = new ArrayList<>(sqlSessionFactories.size());
for (SqlSessionFactory sqlSessionFactory : sqlSessionFactories.values()) {
SqlSession sqlSession = new SqlSessionTemplate(sqlSessionFactory);
sqlSessions.add(sqlSession);
}
//Mapper代码增强 每个方法扩展出一个ShardingMapper类,增强为512个方法。
this.needEnhancedClassesArray = needEnhancedClasses.split(",");
this.enhanceMapperClass();
mapperHelperForSharding.setMappers(needEnhancedClassesArray);
mapperHelperForSharding.setSqlSessions(sqlSessions.toArray(new SqlSession[0]));
mapperHelperForSharding.initMapper();
}
4:执行dao方法
因为是动态代理,又返回到TShardingRoutingInvokeFactory。
使用动态代理的原因:Object mapper = this.newMapper(clazz);
beanFactory.registerSingleton(Character.toLowerCase(clazz.getSimpleName().charAt(0))+ clazz.getSimpleName().substring(1), mapper);
bean工厂中只注入了shopOrderMapper ,但是实际执行的时候需要找到增强后的方法
new Invoker() {
@Override
public Object invoke(Invocation invocation) throws Throwable {
Method method = invocation.getMethod();
ShardingMetadata shardingMetadata = getShardingKey(method, invocation.getArgs());//根据分片参数获取schemaName+tableSuffix
if (shardingMetadata == null) {
throw new DataSourceRoutingException("dataSourceRouting error! Method Name:" + method.getName() + " shardingMetadata is null!");
}
//走分库分表环境
logger.debug("TShardingRoutingInvokeFactory routing to sharding db. Method Name:" + method.getName() + ". ShardingKey:" + shardingMetadata.getShardingKey());
Class newClass = clazz;
if (!"".equals(shardingMetadata.getSchemaName())) {
newClass = Class.forName(clazz.getCanonicalName() + "Sharding" + method.getName());//找到对应增强后的class
}
////newMethod:getShopOrderByShopOrderIds0064
Method newMethod = newClass.getMethod(method.getName() + shardingMetadata.getTableSuffix(), method.getParameterTypes());
MapperBasicConfig config = new MapperBasicConfig(newClass, shardingMetadata.getSchemaName());//应该走哪个数据源
final Object mapper = newMyBatisMapper(config);//获取到对应的mapper ShopOrderMapperShardinggetShopOrderByShopOrderIds
try {
ReadWriteSplittingContextInitializer.initReadWriteSplittingContext(invocation.getMethod());//框架会回调此方法,判断数据源类型,获取数据源类型 master or slave
return newMethod.invoke(mapper, invocation.getArgs());//执行dao方法
} finally {
ReadWriteSplittingContextInitializer.clearReadWriteSplittingContext();
}
}
}
TSharding源码阅读的更多相关文章
- TSharding源码阅读-MapperShardingInitializer
/** * 增强Mapper处理总入口:Mapper被mybatis初始化后,在这里做进一步的处理和增强 * * @author qigong on 5/1/15 */ public class Ma ...
- 【原】FMDB源码阅读(三)
[原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...
- 【原】FMDB源码阅读(二)
[原]FMDB源码阅读(二) 本文转载请注明出处 -- polobymulberry-博客园 1. 前言 上一篇只是简单地过了一下FMDB一个简单例子的基本流程,并没有涉及到FMDB的所有方方面面,比 ...
- 【原】FMDB源码阅读(一)
[原]FMDB源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 说实话,之前的SDWebImage和AFNetworking这两个组件我还是使用过的,但是对于 ...
- 【原】AFNetworking源码阅读(六)
[原]AFNetworking源码阅读(六) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这一篇的想讲的,一个就是分析一下AFSecurityPolicy文件,看看AF ...
- 【原】AFNetworking源码阅读(五)
[原]AFNetworking源码阅读(五) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中提及到了Multipart Request的构建方法- [AFHTTP ...
- 【原】AFNetworking源码阅读(四)
[原]AFNetworking源码阅读(四) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇还遗留了很多问题,包括AFURLSessionManagerTaskDe ...
- 【原】AFNetworking源码阅读(三)
[原]AFNetworking源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇的话,主要是讲了如何通过构建一个request来生成一个data tas ...
- 【原】AFNetworking源码阅读(二)
[原]AFNetworking源码阅读(二) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中我们在iOS Example代码中提到了AFHTTPSessionMa ...
随机推荐
- 用Xcode6的Leaks检测内存泄漏
用xcode打开项目之后,选择Product - Profile: 在弹出的窗口中选择Leaks: 然后在设备解锁的情况下,选择Leaks再点击左上角的红色按钮开始运行APP: 红色的柱子表示有内存泄 ...
- Bluetooth篇 开发实例之七 匹配&UUID
匹配和通信是两回事. 1.用过Android系统设置(Setting)的人都知道蓝牙搜索之后可以建立配对和解除配对,但是这两项功能的函数没有在SDK中给出.但是可以通过反射来获取. 知道这两个API的 ...
- Winform打砖块游戏制作step by step第6节---画墙(砖块集合)以及双缓冲实现
一 引子 为了让更多的编程初学者,轻松愉快地掌握面向对象的思考方法,对象继承和多态的妙用,故推出此系列随笔,还望大家多多支持. 预备知识,无GDI画图基础的童鞋请先阅读一篇文章让你彻底弄懂WinFor ...
- JAVA常见算法题(十八)
package com.xiaowu.demo; /** * 两个乒乓球队进行比赛,各出三人.甲队为a,b,c三人,乙队为x,y,z三人,以抽签决定比赛名单. 有人向队员打听比赛的名单:a说他不和x比 ...
- A folder failed to be renamed or moved--安装Android SDK的问题
对于Android是一直想学却一直未学,行动跟不上想法.现在,终于付诸于行动了. 首先,我找的第一个Android的资料是大话企业级Android,前阵子刚看完大话设计模式,通俗易懂,还是比较喜欢这一 ...
- android 中怎样获取IMEI号
1)在Telephony Framework内部.能够直接使用GSMPhone或GeminiPhone提供的接口. KK之前的版本号: IMEI(International Mobile Equipm ...
- EJB vs Spring
转载: Spring 自从2003年发布以来,一直是Java开源框架的奇迹之一.从2000年开始,伴随着B/S架构逐渐引入企业应用软件开发的领域,Java就逐渐成为企业应用开发的主流技术,一直到200 ...
- 转:提高ios通过率的注意点
http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=431 Bugly 技术干货系列内容主要涉及移动开发方向,是由 Bugly 邀请腾讯内 ...
- Java程序猿的JavaScript学习笔记(12——jQuery-扩展选择器)
计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...
- 【Unity】脚本选择打勾的勾选框隐藏
这个问题事实上已经遇到过好几次了.但又没有特别的须要手动勾选,所以也一直都没在意. 今天研究了一下,原来是由于我删除了Start方法...... 所以.仅仅要脚本中没有Start方法,勾选框就会隐藏掉 ...