签入版本
This commit is contained in:
+548
@@ -0,0 +1,548 @@
|
||||
// +======================================================================
|
||||
// | 小蚂蚁云·企业数字化开发平台 [ 加速数字化转型,构建智能未来 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | 核心价值:赋能开发者 · 服务企业 · 共建生态
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2020-2026 小蚂蚁云团队 版权所有
|
||||
// +----------------------------------------------------------------------
|
||||
// | 官方平台: https://www.xiaomayicloud.com
|
||||
// +======================================================================
|
||||
// | 【知识产权声明】
|
||||
// | 1. 权属声明:本软件是受《中华人民共和国著作权法》
|
||||
// | 保护的专有财产,完整版权归小蚂蚁云团队所有
|
||||
// | 2. 权利范围:所有知识产权(商标、专利、著作权、
|
||||
// | 商业秘密等)均归小蚂蚁云团队所有,受法律保护
|
||||
// | 3. 授权性质:用户仅可获得有限的、非独占的使用许可
|
||||
// | 4. 禁止行为:未经书面授权,禁止对本软件本身
|
||||
// | 申请任何知识产权
|
||||
// | 5. 权利保留:未在本协议中明示授予的一切权利
|
||||
// | 均由小蚂蚁云团队保留
|
||||
// +======================================================================
|
||||
// | 【授权状态说明】
|
||||
// | 1. 未授权状态:用户未购买有效的商业许可证
|
||||
// | 2. 商业授权:已购买正式商业许可证的用户
|
||||
// +======================================================================
|
||||
// | 【绝对禁止条款】
|
||||
// | 无论授权状态如何,任何用户均严格禁止以下行为:
|
||||
// | 1. 逆向工程:对软件进行反编译、反汇编、技术破解或任何形式的逆向分析
|
||||
// | 2. 版权破坏:移除、修改、遮挡软件中的版权标识、许可控制或技术保护措施
|
||||
// | 3. 非法传播:复制、分发、出租、出借、转售、再许可本软件或其许可权利
|
||||
// | 4. 竞争性使用:利用本软件的代码、架构、设计开发直接竞争的产品或服务
|
||||
// | 5. 侵权使用:将软件用于侵犯第三方知识产权或其他合法权益的用途
|
||||
// +======================================================================
|
||||
// | 【商业授权许可范围】
|
||||
// | 购买有效商业许可证的用户,在遵守上述禁止条款的前提下,获得:
|
||||
// | 1. 使用权利:在许可证约定的项目数量、开发者数量范围内使用本软件
|
||||
// | 2. 技术支持:商业授权用户可以获取本地开发部署的技术支持服务
|
||||
// | 3. 版本更新:在许可证有效期内获取软件更新、安全补丁和功能增强
|
||||
// | 4. 商业部署:将基于本软件开发的应用程序用于商业运营和生产环境
|
||||
// +======================================================================
|
||||
// | 【许可证获取】
|
||||
// | 1. 获取途径:仅通过小蚂蚁云官方渠道购买(官网、授权代理商),购买记录凭证
|
||||
// | 2. 转让限制:许可证与购买主体绑定,未经书面同意不得转让
|
||||
// | 3. 终止情形:许可证到期、违反协议、破产清算等情况下自动终止
|
||||
// +======================================================================
|
||||
// | 【合法使用要求】
|
||||
// | 1. 仅限用于合法合规的软件研发
|
||||
// | 2. 严禁用于任何违法、侵权或恶意行为
|
||||
// | 3. 严禁违反我国法律法规和政策
|
||||
// +======================================================================
|
||||
// | 【免责声明】
|
||||
// | 因使用本框架导致的以下情况,我们概不负责:
|
||||
// | 1. 项目研发中的意外、疏忽、违约等风险
|
||||
// | 2. 侵犯第三方知识产权或其他合法权益
|
||||
// | 3. 任何直接、间接、附带或衍生一切损失
|
||||
// | 4. 用户违规违法行为的一切法律后果
|
||||
// +======================================================================
|
||||
// | 【协议重要提示】
|
||||
// | 1. 本声明是《小蚂蚁云最终用户许可协议》的摘要版本
|
||||
// | 2. 下载、安装或使用本软件即表示您接受全部协议条款
|
||||
// | 3. 我们保留单方面修改本声明的权利,修改后的版本在官网公布即生效
|
||||
// | 4. 用户有义务定期查看最新版本,继续使用视为接受修改
|
||||
// +======================================================================
|
||||
// | 【侵权举报与合规】
|
||||
// | 1. 知识产权侵权举报:请联系官方客服
|
||||
// | 2. 许可证合规咨询:xiaomayicloud@163.com
|
||||
// | 3. 违规使用将终止授权并追究责任
|
||||
// | 4. 无条件配合司法机关调查取证
|
||||
// | 5. 保留一切法律追诉权利
|
||||
// | 6. 对有效举报和合规建议,我们将给予感谢和奖励
|
||||
// +======================================================================
|
||||
|
||||
package com.xiaomayi.datasource.aspect;
|
||||
|
||||
import com.xiaomayi.datasource.annotation.DataSource;
|
||||
import com.xiaomayi.datasource.context.DataSourceContextHolder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.*;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 数据源切面处理类 - 完整版
|
||||
* 使用Spring AOP实现基于注解的数据源动态切换
|
||||
* 提供完整的切面生命周期方法:前置通知、后置通知、返回通知、异常通知、环绕通知
|
||||
* <p>
|
||||
* 核心功能:
|
||||
* 1. 拦截带有@DataSource注解的方法或类
|
||||
* 2. 在方法执行前根据注解值切换数据源
|
||||
* 3. 在方法执行后恢复原始数据源设置
|
||||
* 4. 提供完整的切面生命周期监控
|
||||
* 5. 保证数据源切换的线程安全和资源清理
|
||||
* <p>
|
||||
* 切面执行顺序:
|
||||
* 1. doBefore() - 前置通知
|
||||
* 2. around() - 环绕通知(包含实际的方法执行)
|
||||
* 3. doAfterReturning()- 返回通知(方法正常返回)
|
||||
* 或 doAfterThrowing()- 异常通知(方法抛出异常)
|
||||
* 4. doAfter() - 后置通知(最终通知)
|
||||
*
|
||||
* @author 小蚂蚁云团队
|
||||
* @since 2024-05-25
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
@Order(1) // 设置切面执行顺序,确保在事务切面之前执行
|
||||
@Slf4j
|
||||
public class DataSourceAspect {
|
||||
|
||||
/**
|
||||
* 数据源切点定义
|
||||
* 使用AspectJ切点表达式定义拦截规则
|
||||
* <p>
|
||||
* 切点表达式说明:
|
||||
* - @annotation: 拦截带有指定注解的方法
|
||||
* - @within: 拦截带有指定注解的类中的所有方法
|
||||
* <p>
|
||||
* 拦截范围:
|
||||
* 1. 任何带有@DataSource注解的方法
|
||||
* 2. 任何在带有@DataSource注解的类中的方法
|
||||
*/
|
||||
@Pointcut("@annotation(com.xiaomayi.datasource.annotation.DataSource) || " +
|
||||
"@within(com.xiaomayi.datasource.annotation.DataSource)")
|
||||
public void dataSourcePointCut() {
|
||||
// 切点方法体为空,仅用于定义切点表达式
|
||||
}
|
||||
|
||||
/**
|
||||
* 前置通知 - 在目标方法执行前执行
|
||||
* 主要用于数据源的初始设置和验证
|
||||
*
|
||||
* @param point 连接点对象
|
||||
* <p>
|
||||
* 执行时机:
|
||||
* - 在目标方法执行之前
|
||||
* - 在环绕通知的proceed()调用之前
|
||||
* <p>
|
||||
* 主要功能:
|
||||
* 1. 验证数据源注解配置
|
||||
* 2. 记录方法开始执行的日志
|
||||
* 3. 准备数据源切换的环境
|
||||
*/
|
||||
@Before("dataSourcePointCut()")
|
||||
public void doBefore(JoinPoint point) {
|
||||
// 获取当前线程ID,用于日志追踪
|
||||
long threadId = Thread.currentThread().getId();
|
||||
|
||||
// 解析数据源注解配置
|
||||
DataSource dataSourceAnnotation = getDataSource(point);
|
||||
|
||||
if (dataSourceAnnotation != null) {
|
||||
String targetDataSourceKey = dataSourceAnnotation.value().name();
|
||||
String originalDataSource = DataSourceContextHolder.getDataSource();
|
||||
|
||||
log.debug("线程[{}] 前置通知 - 准备数据源切换: {} -> {}, 目标方法: {}.{}",
|
||||
threadId,
|
||||
originalDataSource != null ? originalDataSource : "默认(主库)",
|
||||
targetDataSourceKey,
|
||||
point.getSignature().getDeclaringType().getSimpleName(),
|
||||
point.getSignature().getName());
|
||||
|
||||
// 验证数据源是否存在(可选,也可以在切换时验证)
|
||||
validateDataSource(targetDataSourceKey, point);
|
||||
|
||||
} else {
|
||||
log.info("线程[{}] 前置通知 - 未找到数据源注解,使用默认数据源执行方法: {}.{}",
|
||||
threadId,
|
||||
point.getSignature().getDeclaringType().getSimpleName(),
|
||||
point.getSignature().getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 后置通知 - 在目标方法执行后执行(无论是否抛出异常)
|
||||
* 主要用于资源清理和状态恢复的最终保证
|
||||
*
|
||||
* @param point 连接点对象
|
||||
* <p>
|
||||
* 执行时机:
|
||||
* - 在目标方法执行完成后(无论正常返回还是抛出异常)
|
||||
* - 在返回通知或异常通知之后
|
||||
* - 在环绕通知的finally块之后
|
||||
* <p>
|
||||
* 主要功能:
|
||||
* 1. 确保数据源状态最终被清理
|
||||
* 2. 记录方法执行的最终状态
|
||||
* 3. 提供额外的安全保障,防止数据源泄漏
|
||||
*/
|
||||
@After("dataSourcePointCut()")
|
||||
public void doAfter(JoinPoint point) {
|
||||
long threadId = Thread.currentThread().getId();
|
||||
|
||||
log.debug("线程[{}] 后置通知 - 方法执行完成,当前数据源状态: {}, 方法: {}.{}",
|
||||
threadId,
|
||||
DataSourceContextHolder.getDataSourceStatus(),
|
||||
point.getSignature().getDeclaringType().getSimpleName(),
|
||||
point.getSignature().getName());
|
||||
|
||||
// 额外的安全检查:如果发现异常的数据源状态,进行强制清理
|
||||
performSafetyCheck();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回通知 - 在目标方法正常返回后执行
|
||||
* 主要用于记录成功的操作和性能监控
|
||||
*
|
||||
* @param point 连接点对象
|
||||
* @param result 目标方法的返回值
|
||||
* <p>
|
||||
* 执行时机:
|
||||
* - 仅在目标方法正常返回时执行
|
||||
* - 在目标方法执行完成后,后置通知之前
|
||||
* <p>
|
||||
* 主要功能:
|
||||
* 1. 记录方法成功执行的日志
|
||||
* 2. 监控方法执行性能
|
||||
* 3. 处理返回值相关的逻辑(如记录操作结果)
|
||||
*/
|
||||
@AfterReturning(pointcut = "dataSourcePointCut()", returning = "result")
|
||||
public void doAfterReturning(JoinPoint point, Object result) {
|
||||
long threadId = Thread.currentThread().getId();
|
||||
|
||||
// 记录方法成功执行的信息
|
||||
String returnInfo = getReturnValueInfo(result);
|
||||
|
||||
log.debug("线程[{}] 返回通知 - 方法执行成功, 返回值: {}, 方法: {}.{}, 当前数据源: {}",
|
||||
threadId,
|
||||
returnInfo,
|
||||
point.getSignature().getDeclaringType().getSimpleName(),
|
||||
point.getSignature().getName(),
|
||||
DataSourceContextHolder.getDataSourceStatus());
|
||||
|
||||
// 可以在这里添加成功执行的业务逻辑,如:
|
||||
// - 记录操作日志
|
||||
// - 更新监控指标
|
||||
// - 发送成功通知
|
||||
}
|
||||
|
||||
/**
|
||||
* 异常通知 - 在目标方法抛出异常后执行
|
||||
* 主要用于异常处理和数据源状态的异常恢复
|
||||
*
|
||||
* @param point 连接点对象
|
||||
* @param ex 目标方法抛出的异常
|
||||
* <p>
|
||||
* 执行时机:
|
||||
* - 仅在目标方法抛出异常时执行
|
||||
* - 在目标方法执行完成后,后置通知之前
|
||||
* <p>
|
||||
* 主要功能:
|
||||
* 1. 记录方法执行失败的日志
|
||||
* 2. 处理异常情况下的数据源状态
|
||||
* 3. 提供异常恢复机制
|
||||
* 4. 发送异常告警
|
||||
*/
|
||||
@AfterThrowing(pointcut = "dataSourcePointCut()", throwing = "ex")
|
||||
public void doAfterThrowing(JoinPoint point, Throwable ex) {
|
||||
long threadId = Thread.currentThread().getId();
|
||||
|
||||
log.error("线程[{}] 异常通知 - 方法执行失败, 异常: {}, 方法: {}.{}, 当前数据源: {}",
|
||||
threadId,
|
||||
ex.getMessage(),
|
||||
point.getSignature().getDeclaringType().getSimpleName(),
|
||||
point.getSignature().getName(),
|
||||
DataSourceContextHolder.getDataSourceStatus(),
|
||||
ex);
|
||||
|
||||
// 异常处理逻辑
|
||||
handleDataSourceException(ex, point);
|
||||
|
||||
// 可以在这里添加异常处理业务逻辑,如:
|
||||
// - 发送异常告警
|
||||
// - 记录错误日志到数据库
|
||||
// - 执行异常恢复操作
|
||||
}
|
||||
|
||||
/**
|
||||
* 环绕通知 - 在目标方法执行前后执行
|
||||
* 这是最强大的通知类型,可以控制目标方法的执行
|
||||
*
|
||||
* @param point 连接点对象
|
||||
* @return Object 目标方法的执行结果
|
||||
* @throws Throwable 目标方法抛出的任何异常
|
||||
* <p>
|
||||
* 执行时机:
|
||||
* - 包含目标方法的整个执行过程
|
||||
* - 可以控制是否执行目标方法,以及何时执行
|
||||
* <p>
|
||||
* 主要功能:
|
||||
* 1. 实际的数据源切换逻辑
|
||||
* 2. 方法执行时间的监控
|
||||
* 3. 异常处理和资源清理
|
||||
*/
|
||||
@Around("dataSourcePointCut()")
|
||||
public Object around(ProceedingJoinPoint point) throws Throwable {
|
||||
long threadId = Thread.currentThread().getId();
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
// 解析数据源注解配置
|
||||
DataSource dataSourceAnnotation = getDataSource(point);
|
||||
|
||||
if (dataSourceAnnotation == null) {
|
||||
// 没有找到注解,直接执行原方法
|
||||
log.info("线程[{}] 环绕通知 - 未找到数据源注解,直接执行方法: {}.{}",
|
||||
threadId,
|
||||
point.getSignature().getDeclaringType().getSimpleName(),
|
||||
point.getSignature().getName());
|
||||
return point.proceed();
|
||||
}
|
||||
|
||||
String targetDataSourceKey = dataSourceAnnotation.value().name();
|
||||
String originalDataSource = DataSourceContextHolder.getDataSource();
|
||||
Object result = null;
|
||||
boolean success = false;
|
||||
|
||||
log.info("线程[{}] 环绕通知 - 开始数据源切换: {} -> {}, 方法: {}.{}",
|
||||
threadId,
|
||||
originalDataSource != null ? originalDataSource : "默认(主库)",
|
||||
targetDataSourceKey,
|
||||
point.getSignature().getDeclaringType().getSimpleName(),
|
||||
point.getSignature().getName());
|
||||
|
||||
try {
|
||||
// 设置新的数据源
|
||||
DataSourceContextHolder.setDataSource(targetDataSourceKey);
|
||||
|
||||
// 执行目标方法
|
||||
result = point.proceed();
|
||||
success = true;
|
||||
|
||||
return result;
|
||||
|
||||
} catch (Throwable ex) {
|
||||
// 记录异常信息,但不需要在这里处理,异常通知会处理
|
||||
success = false;
|
||||
throw ex;
|
||||
|
||||
} finally {
|
||||
// 计算执行时间
|
||||
long executionTime = System.currentTimeMillis() - startTime;
|
||||
|
||||
// 恢复数据源设置
|
||||
DataSourceContextHolder.clearDataSource();
|
||||
|
||||
// 记录执行结果
|
||||
log.info("线程[{}] 环绕通知 - 方法执行{},耗时: {}ms, 方法: {}.{}, 数据源状态: {}",
|
||||
threadId,
|
||||
success ? "成功" : "失败",
|
||||
executionTime,
|
||||
point.getSignature().getDeclaringType().getSimpleName(),
|
||||
point.getSignature().getName(),
|
||||
DataSourceContextHolder.getDataSourceStatus());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证数据源是否存在
|
||||
*
|
||||
* @param dataSourceKey 数据源标识
|
||||
* @param point 连接点对象
|
||||
*/
|
||||
private void validateDataSource(String dataSourceKey, JoinPoint point) {
|
||||
try {
|
||||
// 这里可以添加数据源验证逻辑
|
||||
// 例如:检查数据源是否在配置中启用
|
||||
// 由于数据源验证主要在DynamicDataSource中完成,这里主要做日志记录
|
||||
|
||||
log.info("数据源验证 - 数据源: {} 准备用于方法: {}.{}",
|
||||
dataSourceKey,
|
||||
point.getSignature().getDeclaringType().getSimpleName(),
|
||||
point.getSignature().getName());
|
||||
|
||||
} catch (Exception e) {
|
||||
log.warn("数据源验证失败 - 数据源: {}, 方法: {}.{}, 错误: {}",
|
||||
dataSourceKey,
|
||||
point.getSignature().getDeclaringType().getSimpleName(),
|
||||
point.getSignature().getName(),
|
||||
e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行安全检查
|
||||
* 防止数据源状态异常导致的内存泄漏或数据污染
|
||||
*/
|
||||
private void performSafetyCheck() {
|
||||
try {
|
||||
// 检查当前线程的数据源状态
|
||||
String currentDataSource = DataSourceContextHolder.getDataSource();
|
||||
|
||||
// 如果发现异常的数据源状态,进行强制清理
|
||||
if (currentDataSource != null && currentDataSource.contains("ERROR")) {
|
||||
log.warn("安全检查 - 检测到异常数据源状态: {}, 进行强制清理", currentDataSource);
|
||||
DataSourceContextHolder.clearAll();
|
||||
}
|
||||
|
||||
// 可以添加更多的安全检查逻辑
|
||||
// 例如:检查线程是否长时间持有数据源
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("安全检查执行失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理数据源相关异常
|
||||
*
|
||||
* @param ex 异常对象
|
||||
* @param point 连接点对象
|
||||
*/
|
||||
private void handleDataSourceException(Throwable ex, JoinPoint point) {
|
||||
try {
|
||||
// 记录异常相关的数据源信息
|
||||
String dataSourceStatus = DataSourceContextHolder.getDataSourceStatus();
|
||||
|
||||
// 如果是数据源连接异常,可以尝试恢复或告警
|
||||
if (isDataSourceConnectionException(ex)) {
|
||||
log.error("数据源连接异常 - 方法: {}.{}, 数据源状态: {}, 异常: {}",
|
||||
point.getSignature().getDeclaringType().getSimpleName(),
|
||||
point.getSignature().getName(),
|
||||
dataSourceStatus,
|
||||
ex.getMessage());
|
||||
|
||||
// 可以在这里添加连接异常的处理逻辑
|
||||
// 例如:发送告警、记录到监控系统等
|
||||
}
|
||||
|
||||
// 确保在异常情况下数据源状态被正确清理
|
||||
DataSourceContextHolder.clearAll();
|
||||
|
||||
} catch (Exception handlerEx) {
|
||||
log.error("处理数据源异常时发生错误", handlerEx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否是数据源连接异常
|
||||
*
|
||||
* @param ex 异常对象
|
||||
* @return boolean true-是数据源连接异常,false-不是
|
||||
*/
|
||||
private boolean isDataSourceConnectionException(Throwable ex) {
|
||||
if (ex == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String message = ex.getMessage();
|
||||
if (message == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 根据异常信息判断是否是数据源连接问题
|
||||
return message.contains("Connection") ||
|
||||
message.contains("DataSource") ||
|
||||
message.contains("SQL") ||
|
||||
message.contains("JDBC") ||
|
||||
ex.getClass().getName().contains("SQL");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取返回值信息(用于日志记录)
|
||||
*
|
||||
* @param result 方法返回值
|
||||
* @return String 返回值描述信息
|
||||
*/
|
||||
private String getReturnValueInfo(Object result) {
|
||||
if (result == null) {
|
||||
return "null";
|
||||
}
|
||||
|
||||
try {
|
||||
if (result instanceof Iterable) {
|
||||
// 如果是集合类型,返回元素数量
|
||||
int size = 0;
|
||||
for (Object item : (Iterable<?>) result) {
|
||||
size++;
|
||||
if (size > 10) break; // 防止大集合的遍历
|
||||
}
|
||||
return String.format("Collection[%d elements]", size);
|
||||
} else if (result.getClass().isArray()) {
|
||||
// 如果是数组,返回长度
|
||||
return String.format("Array[%d]", java.lang.reflect.Array.getLength(result));
|
||||
} else {
|
||||
// 其他类型返回简单类名
|
||||
return result.getClass().getSimpleName();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return "Error getting return info: " + e.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据源注解配置
|
||||
* 按照优先级查找@DataSource注解:方法级别 > 类级别
|
||||
*
|
||||
* @param point 连接点对象
|
||||
* @return DataSource 数据源注解实例,如果未找到返回null
|
||||
*/
|
||||
private DataSource getDataSource(JoinPoint point) {
|
||||
if (!(point.getSignature() instanceof MethodSignature)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
MethodSignature signature = (MethodSignature) point.getSignature();
|
||||
|
||||
// 查找方法级别的@DataSource注解
|
||||
DataSource methodAnnotation = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class);
|
||||
|
||||
if (Objects.nonNull(methodAnnotation)) {
|
||||
return methodAnnotation;
|
||||
}
|
||||
|
||||
// 查找类级别的@DataSource注解
|
||||
return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取切面状态信息(用于监控和调试)
|
||||
*
|
||||
* @return String 切面状态描述
|
||||
*/
|
||||
public String getAspectStatus() {
|
||||
return String.format("DataSourceAspect[激活状态: 已启用, 切面顺序: %d, 通知类型: 完整, 当前线程数据源: %s]",
|
||||
1,
|
||||
DataSourceContextHolder.getDataSourceStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查切面是否正常工作(用于健康检查)
|
||||
*
|
||||
* @return boolean true-正常,false-异常
|
||||
*/
|
||||
public boolean isAspectHealthy() {
|
||||
try {
|
||||
// 测试基本的切面功能
|
||||
DataSourceContextHolder.getDataSource();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error("数据源切面健康检查失败", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user