注解实现自定义异常抛出
背景
公司项目数据源并非DB,目前已经对该数据源的表数据操作进行封装复用,但此数据源创建、删除、修改操作只会返回布尔值,业务逻辑中如果是此数据源操作出现问题,需返回前端异常信息为此数据源操作异常,因为数据表繁多,业务逻辑判断中也会出现很多抛出自定义异常的重复代码。为了减少不必要代码的产生,需要将异常抛出下沉,不在业务逻辑中重复抛出异常的方法。
实现思路
受限于数据源,每个表都会写一个单独的Manager.java去处理一些数据二次转换以及封装问题,此数据源创建、删除、修改操作对于底层都是数据字段的set操作,如果想要异常描述更清晰,只能在Manager.java中实现异常处理,而不是更底层的方法。
1. 创建一个注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExceptionThrow {
/**
* 被操作资源表
* @return {@link ResourceTypeEnum}
*/
ResourceTypeEnum resourceType();
/**
* 操作
* @return {@link OperationEnum}
*/
OperationEnum operation();
/**
* 要抛出异常的类型,默认mb操作失败异常
* @return {@link GlobalExceptionEnum}
*/
GlobalExceptionEnumexception() default GlobalExceptionEnum.mb_set_fail;
/**
* 数据源
* @return {@link DataSourceEnum}
*/
DataSourceEnum dataSource() default DataSourceEnum.MB;
enum OperationEnum {
select, create, delete, update
}
enum DataSourceEnum {
MB, DB
}
2. 创建一个注解处理类
@Aspect
@Component
@Slf4j
public class ExceptionThrowAspect {
@Around(@annotation(ExceptionThrow))
public Object aroundMibCut(ProceedingJoinPoint joinPoint) {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method == null) {
log.warn("ExceptionThrowAspect method is null!!!");
return new Object();
}
ExceptionThrow exceptionThrow = method.getAnnotation(ExceptionThrow.class);
Object dataId = null;
// 方法参数值
Object[] args = joinPoint.getArgs();
Object obj = new Object();
try {
obj = joinPoint.proceed();
Parameter[] parameters = method.getParameters();
// 遍历出id的值
for (int i = 0; i < parameters.length; i++) {
if ("id".equals(parameters[i].getName())) {
dataId = args[i];
break;
}
}
} catch (Throwable e) {
e.printStackTrace();
log.warn("ExceptionThrowAspect for do ({}) exception:{}", signature.getName(), e.getMessage());
}
throwException(obj, dataId, exceptionThrow);
return obj;
}
/**
* 格式化异常的信息描述
*
* @param obj 方法逻辑结果
* @param dataId mb/db数据主键
* @param exceptionThrow {@link ExceptionThrow} 操作类型
*/
private void throwException(Object obj, Object dataId, ExceptionThrow exceptionThrow) {
// 不同数据源抛出异常的条件
boolean throwException = ExceptionThrow.DataSourceEnum.MB== exceptionThrow.dataSource() ? !((boolean) obj) : obj == null;
if (throwException && dataId != null) {
String template = "{} {}, "+ exceptionThrow.dataSource().name() +" id is {} !";
String msg = StrUtil.format(template, exceptionThrow.operation(), exceptionThrow.resourceType().name(), dataId);
throw new OtnGlobalException(exceptionThrow.exception(), msg);
}
}
有特殊异常处理的方法可以使用该注解。水平有限,欢迎指教。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程