提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
本文主要描述面向切面编程AOP的用例
一、AOP是什么?
利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率
二、使用步骤
1.引入pom文件依赖
代码如下(示例):
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> <version>2.6.4</version> </dependency>
2.请求日志记录
代码如下(示例):
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface OptLog {
/**
* 操作日志类型
*
* @return
*/
OperationTypeEnum scenesType();
/**
* 请求处理状态
*
* @return
*/
int status() default 0;
/**
* 写SpEL表达式 获取request请求内容
*
* @return
*/
String request() default "";
/**
* request请求内容的类型
*
* @return
*/
Class<?> requestType() default String.class;
/**
* 默认 系统管理员
* 其他的取当前登录人
*
* @return
*/
String operationUser() default "系统管理员";
/**
* 默认 系统管理员
* 其他的取当前登录人
*
* @return
*/
long operationUserId() default 0L;
}
@Slf4j
@Aspect
@Component
public class OptLogAspect {
/**
* 用于SpEL表达式解析.
*/
private final SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
/**
* 用于获取方法参数定义名字.
*/
private final DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();
@Autowired
private InLogRepository inLogRepository;
@Pointcut("@annotation(com.yssk.interfaces.biz.annotation.OptLog)")
public void optLogAspect() {
}
@Around("optLogAspect()")
public Object doAround(ProceedingJoinPoint joinPoint) {
Object obj = null;
try {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
//获取方法参数值
Object[] args = joinPoint.getArgs();
OptLog optLog = getTargetAnnotation(joinPoint);
String request = optLog.request();
Class<?> requestType = optLog.requestType();
// 获取request请求内容
Object requestKeyVal = getValBySpEl(request, methodSignature, args, requestType);
if(Objects.nonNull(requestKeyVal)){
Long id = handleOptRecordBefore(requestKeyVal);
log.info("rizhi:{}", id);
obj = joinPoint.proceed();
handleOptRecordAfter(id, obj);
}
} catch (Throwable e) {
log.warn("记录请求日志出现异常...", e);
}
return obj;
}
private Long handleOptRecordBefore(Object request){
log.info("请求日志保存");
String jsonStr = JSONObject.toJSONString(request);
String requestUrl = "";
if(ObjectUtils.isNotEmpty(request)){
if(request instanceof RequestDTO){
requestUrl = ((RequestDTO<?>) request).getRequestUrl();
}
}
// 保存请求日志
InLog inLog = new InLog();
inLog.setRequest(jsonStr);
inLog.setRequestUrl(requestUrl);
inLog.setStatus(0);
inLogRepository.save(inLog);
return inLog.getId();
}
private void handleOptRecordAfter(Long id, Object response){
log.info("请求日志修改");
String jsonStr = JSONObject.toJSONString(response);
int status = 0;
if(ObjectUtils.isNotEmpty(response)){
if(response instanceof ResponseDTO){
if(((ResponseDTO<?>) response).getError_code() == 0){
status = 1;
}
}
}
// 修改请求日志
LambdaUpdateWrapper<InLog> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.set(InLog::getStatus, status);
updateWrapper.eq(InLog::getId, id);
updateWrapper.set(InLog::getResponse, jsonStr);
inLogRepository.update(updateWrapper);
}
/**
* 获取注解
* @param point
* @return
*/
public static OptLog getTargetAnnotation(JoinPoint point) {
try {
OptLog annotation = null;
if (point.getSignature() instanceof MethodSignature) {
Method method = ((MethodSignature) point.getSignature()).getMethod();
if (method != null) {
annotation = method.getAnnotation(OptLog.class);
}
}
return annotation;
} catch (Exception e) {
log.warn("获取 {}.{} 的 @OptLog 注解失败", point.getSignature().getDeclaringTypeName(), point.getSignature().getName(), e);
return null;
}
}
/**
* 解析spEL表达式
*/
private Object getValBySpEl(String spEl, MethodSignature methodSignature, Object[] args, Class<?> classType) {
try {
//获取方法形参名数组
String[] paramNames = nameDiscoverer.getParameterNames(methodSignature.getMethod());
if (paramNames != null && paramNames.length > 0) {
Expression expression = spelExpressionParser.parseExpression(spEl);
// spring的表达式上下文对象
EvaluationContext context = new StandardEvaluationContext();
// 给上下文赋值
for (int i = 0; i < args.length; i++) {
context.setVariable(paramNames[i], args[i]);
context.setVariable("p" + i, args[i]);
}
return expression.getValue(context, classType);
}
} catch (Exception e) {
log.warn("解析请求日志的el表达式出错", e);
}
return null;
}
}
总结
以上就是今天要讲的内容,本文仅仅简单介绍了aop的使用法。