博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
TSharding源码阅读-MapperShardingInitializer
阅读量:6824 次
发布时间:2019-06-26

本文共 9599 字,大约阅读时间需要 31 分钟。

  hot3.png

 
/** * 增强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
sqlSessionFactories = applicationContext.getBeansOfType(SqlSessionFactory.class); if (sqlSessionFactories.isEmpty()) { return; } MapperHelperForSharding mapperHelperForSharding = new MapperHelperForSharding(); List
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
getShopOrderByShopOrderIds(@ShardingOrderPara List
paramList); @ShardingExtensionMethod(type=MapperResourceEnhancer.class, method="enhancedShardingSQL") public abstract int batchUpdateShopOrderByShopOrderIds(@ShardingOrderPara @Param("shopOrderIds") List
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
 

转载于:https://my.oschina.net/sbcagf/blog/783057

你可能感兴趣的文章
经典脚本案例--check memory
查看>>
20.31 expect脚本同步文件;20.32 expect脚本指定host和要同步的文件;20.33 构建文件分发系统;20.34...
查看>>
CentOS单用户与救援模式
查看>>
postfix 源码centos7上搭建及错误提示---亲测
查看>>
【Redis篇】Redis集群安装与初始
查看>>
jquery基础
查看>>
C# 集合已修改;可能无法执行枚举操作
查看>>
FSM Code Generator
查看>>
JDBC学习笔记——事务、存储过程以及批量处理
查看>>
JVM内存结构
查看>>
Java 锁
查看>>
7、索引在什么情况下遵循最左前缀的规则?
查看>>
c#中委托与事件
查看>>
mysql数据库备份之主从同步配置
查看>>
angularJs(1)指令篇
查看>>
自定义Xadmin
查看>>
jsp页面表单的遍历要怎么写
查看>>
循环引用,看我就对了
查看>>
软件工程——第一周作业
查看>>
ubuntu14.04安装vmware workstation
查看>>