6 changed files with 933 additions and 88 deletions
@ -0,0 +1,66 @@ |
|||
package com.example.web.aspect; |
|||
|
|||
import com.example.web.config.DataSourceContextHolder; |
|||
import org.aspectj.lang.JoinPoint; |
|||
import org.aspectj.lang.annotation.After; |
|||
import org.aspectj.lang.annotation.Aspect; |
|||
import org.aspectj.lang.annotation.Before; |
|||
import org.aspectj.lang.annotation.Pointcut; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
@Aspect |
|||
@Component |
|||
public class ReadWriteSeparationAspect { |
|||
|
|||
private static final Logger logger = LoggerFactory.getLogger(ReadWriteSeparationAspect.class); |
|||
|
|||
// 定义切入点,拦截所有Mapper方法
|
|||
@Pointcut("execution(* com.example.web.mapper.*Mapper.*(..))") |
|||
public void mapperPointcut() { |
|||
} |
|||
|
|||
@Before("mapperPointcut()") |
|||
public void beforeMapperMethod(JoinPoint joinPoint) { |
|||
String methodName = joinPoint.getSignature().getName(); |
|||
String className = joinPoint.getTarget().getClass().getSimpleName(); |
|||
|
|||
// 获取当前使用的数据源
|
|||
String currentDataSource = DataSourceContextHolder.getDataSource(); |
|||
|
|||
// 根据方法名判断是读操作还是写操作
|
|||
if (isReadOperation(methodName)) { |
|||
// 读操作使用从库
|
|||
String slaveDataSource = currentDataSource.contains("wechat") ? "wechat-slave" : "primary-slave"; |
|||
DataSourceContextHolder.setDataSource(slaveDataSource); |
|||
logger.debug("切换到从库数据源: {},执行方法: {}.{}", slaveDataSource, className, methodName); |
|||
} else { |
|||
// 写操作使用主库
|
|||
String masterDataSource = currentDataSource.contains("wechat") ? "wechat" : "primary"; |
|||
DataSourceContextHolder.setDataSource(masterDataSource); |
|||
logger.debug("切换到主库数据源: {},执行方法: {}.{}", masterDataSource, className, methodName); |
|||
} |
|||
} |
|||
|
|||
@After("mapperPointcut()") |
|||
public void afterMapperMethod() { |
|||
// 方法执行完成后清除数据源上下文
|
|||
DataSourceContextHolder.clearDataSource(); |
|||
} |
|||
|
|||
/** |
|||
* 判断是否为读操作 |
|||
* @param methodName 方法名 |
|||
* @return 是否为读操作 |
|||
*/ |
|||
private boolean isReadOperation(String methodName) { |
|||
// 通常查询方法以find、get、select、query、list、count等开头的方法为读操作
|
|||
return methodName.startsWith("find") || |
|||
methodName.startsWith("get") || |
|||
methodName.startsWith("select") || |
|||
methodName.startsWith("query") || |
|||
methodName.startsWith("list") || |
|||
methodName.startsWith("count"); |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
Loading…
Reference in new issue