package com.mogujie.trade.tsharding.route.orm.base; import com.mogujie.trade.db.DataSourceType; import com.mogujie.trade.db.ReadWriteSplitting; import com.mogujie.trade.db.ReadWriteSplittingContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.reflect.Method; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * 读写分离的上下文初始化和清空 * * @author qigong */ public class ReadWriteSplittingContextInitializer { private final static Logger logger = LoggerFactory.getLogger(ReadWriteSplittingContextInitializer.class); private final static String[] DEFAULT_WRITE_METHOD_NAMES = {"update", "save", "insert", "delete", "add", "batchInsert", "batchUpdate", "batchSave", "batchAdd"}; private final static Map<Method, DataSourceType> cache = new ConcurrentHashMap<>(); public static void initReadWriteSplittingContext(Method method) { // 忽略object的方法,只关注Mapper的方法 if (method.getDeclaringClass() != Object.class) { } DataSourceType dataSourceType = getDataSourceType(method); logger.debug("ReadWriteSplitting {} using dataSource of {}", method, dataSourceType); ReadWriteSplittingContext.set(dataSourceType); } public static void clearReadWriteSplittingContext() { ReadWriteSplittingContext.clear(); } /** * 获取方法对应的数据眼类型 * * @param method * @return */ private static DataSourceType getDataSourceType(Method method) { DataSourceType dataSourceType = cache.get(method); if (dataSourceType == null) { synchronized (method) { dataSourceType = cache.get(method); if (dataSourceType == null) { dataSourceType = determineDataSourceType(method); cache.put(method, dataSourceType); } } } return dataSourceType; } private static DataSourceType determineDataSourceType(Method method) { DataSourceType dataSourceType = DataSourceType.slave; ReadWriteSplitting readWriteSplitting = method.getAnnotation(ReadWriteSplitting.class); if (readWriteSplitting != null) { dataSourceType = readWriteSplitting.value(); dataSourceType = dataSourceType == null ? DataSourceType.master : dataSourceType; } else { for (String writeMethodName : DEFAULT_WRITE_METHOD_NAMES) { if (method.getName().startsWith(writeMethodName)) { dataSourceType = DataSourceType.master; break; } } } return dataSourceType; } }