TSharding源码阅读-MapperShardingInitializer
/**
* 增强Mapper处理总入口:Mapper被mybatis初始化后,在这里做进一步的处理和增强
*
* @author qigong on 5/1/15
*/
public class MapperShardingInitializer implements ApplicationContextAware { Logger logger = LoggerFactory.getLogger(getClass()); private String needEnhancedClasses;
private String[] needEnhancedClassesArray; @Override
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();
} private void enhanceMapperClass() {
for (String mapperClass : needEnhancedClassesArray) {
try {
MapperEnhancer.enhanceMapperClass(mapperClass);
} catch (Exception e) {
logger.error("Enhance {} class error", mapperClass, e);
}
}
} public void setNeedEnhancedClasses(String needEnhancedClasses) {
this.needEnhancedClasses = needEnhancedClasses;
}
}
3.1 this.enhanceMapperClass();
/**
* 对mapper进行增强,生成新的mapper,并主动加载新mapper类到classloader
*
* @param mapperClassName
*/
public static void enhanceMapperClass(String mapperClassName) throws Exception {
//com.mogujie.service.tsharding.mapper.ShopOrderMapper
Class originClass = Class.forName(mapperClassName);//获取A
Method[] originMethods = originClass.getDeclaredMethods();//获取A的方法, CtClass cc = pool.get(mapperClassName);//获取到class定义的容器ClassPool,通过它获取已经编译好的类A for (CtMethod ctMethod : cc.getDeclaredMethods()) {//遍历A的所有方法
CtClass enhanceClass = pool.makeInterface(mapperClassName + "Sharding" + ctMethod.getName());//针对A的每一个方法新建一个接口B
//com.mogujie.service.tsharding.mapper.ShopOrderMapperShardinggetShopOrderByShopOrderId
for (long i = 0L; i < 512; i++) {//生成512个方法
CtMethod newMethod = new CtMethod(ctMethod.getReturnType(), ctMethod.getName() + ShardingCaculator.getNumberWithZeroSuffix(i), ctMethod.getParameterTypes(), enhanceClass);
//CtMethod 和CtConstructor 提供了 insertBefore()、insertAfter()和 addCatch()方法,它们可以插入一个souce文本到存在的方法的相应的位置
Method method = getOriginMethod(newMethod, originMethods);//获取A的方法
if(method.getParameterAnnotations()[0].length > 0) {//如果带注解
ClassFile ccFile = enhanceClass.getClassFile();
ConstPool constPool = ccFile.getConstPool(); //拷贝注解信息和注解内容,以支持mybatis mapper类的动态绑定
newMethod.getMethodInfo().addAttribute(MapperAnnotationEnhancer.duplicateParameterAnnotationsAttribute(constPool, method));
}
enhanceClass.addMethod(newMethod);//B增加方法
}
Class<?> loadThisClass = enhanceClass.toClass(); //2015.09.22后不再输出类到本地
enhanceClass.writeFile(".");
}
}
需要增强的类
@DataSourceRouting(handler=TShardingRoutingHandler.class)
public abstract interface ShopOrderMapper
{
@ShardingExtensionMethod(type=MapperResourceEnhancer.class, method="enhancedShardingSQL")
public abstract ShopOrder getShopOrderByShopOrderId(@ShardingOrderPara Long paramLong); @ShardingExtensionMethod(type=MapperResourceEnhancer.class, method="enhancedShardingSQL")
public abstract List<ShopOrder> getShopOrderByShopOrderIds(@ShardingOrderPara List<Long> paramList); @ShardingExtensionMethod(type=MapperResourceEnhancer.class, method="enhancedShardingSQL")
public abstract int batchUpdateShopOrderByShopOrderIds(@ShardingOrderPara @Param("shopOrderIds") List<Long> paramList, @Param("shopOrder") ShopOrder paramShopOrder);
}
增强后针对每一个方法都生成了一个类
public abstract interface ShopOrderMapperShardingbatchUpdateShopOrderByShopOrderIds
{
public abstract int batchUpdateShopOrderByShopOrderIds0000(@ShardingOrderPara("orderId") @Param("shopOrderIds") List paramList, @Param("shopOrder") ShopOrder paramShopOrder); public abstract int batchUpdateShopOrderByShopOrderIds0001(@ShardingOrderPara("orderId") @Param("shopOrderIds") List paramList, @Param("shopOrder") ShopOrder paramShopOrder); public abstract int batchUpdateShopOrderByShopOrderIds0002(@ShardingOrderPara("orderId") @Param("shopOrderIds") List paramList, @Param("shopOrder") ShopOrder paramShopOrder); public abstract int batchUpdateShopOrderByShopOrderIds0003(@ShardingOrderPara("orderId") @Param("shopOrderIds") List paramList, @Param("shopOrder") ShopOrder paramShopOrder); public abstract int batchUpdateShopOrderByShopOrderIds0004(@ShardingOrderPara("orderId") @Param("shopOrderIds") List paramList, @Param("shopOrder") ShopOrder paramShopOrder);
public abstract interface ShopOrderMapperShardinggetShopOrderByShopOrderId
{
public abstract ShopOrder getShopOrderByShopOrderId0000(@ShardingOrderPara("orderId") Long paramLong); public abstract ShopOrder getShopOrderByShopOrderId0001(@ShardingOrderPara("orderId") Long paramLong); public abstract ShopOrder getShopOrderByShopOrderId0002(@ShardingOrderPara("orderId") Long paramLong); public abstract ShopOrder getShopOrderByShopOrderId0003(@ShardingOrderPara("orderId") Long paramLong); public abstract ShopOrder getShopOrderByShopOrderId0004(@ShardingOrderPara("orderId") Long paramLong); public abstract ShopOrder getShopOrderByShopOrderId0005(@ShardingOrderPara("orderId") Long paramLong); public abstract ShopOrder getShopOrderByShopOrderId0006(@ShardingOrderPara("orderId") Long paramLong); public abstract ShopOrder getShopOrderByShopOrderId0007(@ShardingOrderPara("orderId") Long paramLong);
}
public abstract interface ShopOrderMapperShardinggetShopOrderByShopOrderIds
{
public abstract List getShopOrderByShopOrderIds0000(@ShardingOrderPara("orderId") List paramList); public abstract List getShopOrderByShopOrderIds0001(@ShardingOrderPara("orderId") List paramList); public abstract List getShopOrderByShopOrderIds0002(@ShardingOrderPara("orderId") List paramList); public abstract List getShopOrderByShopOrderIds0003(@ShardingOrderPara("orderId") List paramList); public abstract List getShopOrderByShopOrderIds0004(@ShardingOrderPara("orderId") List paramList); public abstract List getShopOrderByShopOrderIds0005(@ShardingOrderPara("orderId") List paramList); public abstract List getShopOrderByShopOrderIds0006(@ShardingOrderPara("orderId") List paramList); public abstract List getShopOrderByShopOrderIds0007(@ShardingOrderPara("orderId") List paramList);
}
3.2 mapperHelperForSharding.setMappers(needEnhancedClassesArray);
通过ShopOrderMapper.java,获取注解配置 @ShardingExtensionMethod(type = MapperResourceEnhancer.class, method = "enhancedShardingSQL"),
生成MapperEnhancer,以ShopOrderMapper的方法名为key,MapperResourceEnhancer.enhancedShardingSQL 为value,保存在MapperResourceEnhancer.methodMap中。
返回MapperEnhancer,再以ShopOrderMappe 为key,MapperEnhancer为value,保存在MapperHelperForSharding.registerMapper中,供后续使用
3.3 mapperHelperForSharding.setSqlSessions(sqlSessions.toArray(new SqlSession[0]));
把sqlSession保存在mapperHelperForSharding.sqlSessions
3.4 mapperHelperForSharding.initMapper();( Spring4 is necessary)
类关系:SqlSession>Configuration>MappedStatement>DynamicSqlSource||RawSqlSource
遍历 sqlSessions,处理Configuration中全部的MappedStatement,重新设置SqlSource。
重新设置SqlSource:获取MapperTemplate(3.2mapperHelperForSharding.registerMapper中保存的MapperEnhancer)。
然后 mapperEnhancer.setSqlSource(ms, configuration);代码增强 扩充为512个方法。
public void setSqlSource(MappedStatement ms, Configuration configuration) throws Exception {
Method method = methodMap.get(getMethodName(ms));//3.2中保存的enhancedShardingSQL方法
try {
if (method.getReturnType() == Void.TYPE) {
method.invoke(this, ms);
} else if (SqlSource.class.isAssignableFrom(method.getReturnType())) {
//代码增强 扩充为512个方法。
for (long i = 0; i < 512; i++) {
//新的带sharding的sql
SqlSource sqlSource = (SqlSource) method.invoke(this, ms, configuration, i);
String newMsId = ms.getId() + ShardingCaculator.getNumberWithZeroSuffix(i);
newMsId = newMsId.replace("Mapper.", "MapperSharding" + getMethodName(ms) + ".");
//添加到ms库中
MappedStatement newMs = copyFromMappedStatement(ms, sqlSource, newMsId);
configuration.addMappedStatement(newMs);
setSqlSource(newMs, sqlSource);
}
} else {
throw new RuntimeException("自定义Mapper方法返回类型错误,可选的返回类型为void和SqlNode!");
}
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e.getTargetException() != null ? e.getTargetException() : e);
}
}
3.4.1 SqlSource sqlSource = (SqlSource) method.invoke(this, ms, configuration, i);
实际调用com.mogujie.trade.tsharding.route.orm.MapperResourceEnhancer;enhancedShardingSQL
(SqlSession>Configuration>MappedStatement>DynamicSqlSource||RawSqlSource)
DynamicSqlSource中存在mapperxml中每个节点的语句。
awSqlSource中存在mapperxml中的sql语句。根据分片参数替换成对应的表名,比如TradeOrder0066
最终生成的sql语句类似(SELECT orderId, buyerUserId,sellerUserId FROM TradeOrder0066 WHERE orderId = ? limit 1)
用新ID,创建MappedStatement(mapperxml节点),添加到Configuration,设置数据源
新ID格式:com.mogujie.service.tsharding.mapper.ShopOrderMapperShardinggetShopOrderByShopOrderId.getShopOrderByShopOrderId0000
TSharding源码阅读-MapperShardingInitializer的更多相关文章
- TSharding源码阅读
需要的背景知识:Spring 和Mybatis 实现原理和源码, javaassist字节码增强的使用, java及设计模式的使用 1 读取解析数据库配置文件 DataSourceScanner实现了 ...
- 【原】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 ...
随机推荐
- 设计模式之观察者模式(php实现)
github地址:https://github.com/ZQCard/design_pattern /** * 当对象间存在一对多关系时,则使用观察者模式(Observer Pattern). * 比 ...
- 管理 node 版本,选择 nvm 还是 n?
来源:http://taobaofed.org/blog/2015/11/17/nvm-or-n/ 引子 我本机安装着 nvm,而 node 本来一直运行在 0.x 的老版本上.后来为了跑 ES6,我 ...
- apache 返回的状态码304
博客转载:http://baike.baidu.com/link?url=jhw62dpK66WD7EQFKWEhVQs_jPeFKIUegnA6 如果客户端发送了一个带条件的GET 请求且该请求已被 ...
- 矩阵压缩写法 scipy spark.ml.linalg里都有,CRS,CCS
CRS 表示:Compressed Row Storage CCS 表示:Compressed Column Storage CRS的表示参考: https://blog.csdn.net/buptf ...
- MPTCP 源码分析(一) MPTCP的三次握手
简述: MPTCP依然按照正常的TCP进行三次握手,只是在握手过程中增加了MPTCP特有的信息. 建立过程 三次握手过程如下图所示: 左边客户端发送的第一个SYN包携带有客户端 ...
- iptables firewall-cmd
iptables -F iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT iptables -A IN ...
- Metadata publishing for this service is currently disabled.
Reason 1: In your web.config <service name="A.B.C"> but your class is: namespace A.B ...
- Unity3D的三种坐标系
来自:http://blog.csdn.net/luxiaoyu_sdc/article/details/13168497 1, World Space(世界坐标): 我们在场景中添加物体(如:Cub ...
- 关于八数码问题中的状态判重的三种解决方法(编码、hash、<set>)
八数码问题搜索有非常多高效方法:如A*算法.双向广搜等 但在搜索过程中都会遇到同一个问题.那就是判重操作(假设反复就剪枝),怎样高效的判重是8数码问题中效率的关键 以下关于几种判重方法进行比較:编码. ...
- CSS——如何清除浮动
众所周知,平时在写HTML代码时,难免少不了使用Float样式,这样一来,假使您没有清除浮动,那么有浮动元素的父元素容器将元素将无法自动撑开.换句简单好理解的话来说,假如你在写CODE时,其中div. ...