SpringBootWeb AOP
事务管理
rollbackFor属性
propagation属性
REQUIRED:大部分情况下都是用该传播行为即可。
REOUIRES_NEW:当我们不希望事务之间相互影响时,可以使用该传播行为。比如:下订单前需要记录日志,不论订单保存成功与否,都需要保证日志记录能够记录成功。
案例
Grep Console插件可用于日志过滤筛选
AOP
基础
进阶
通知类型
@Slf4j
@Component
@Aspect
public class MyAspect1 {
@Pointcut("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
public void pt() {
}
@Before("pt()")
public void before() {
log.info("before ...");
}
@Around("pt()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
log.info("around before ...");
//调用目标对象的原始方法执行
Object result = proceedingJoinPoint.proceed();
log.info("around after ...");
return result;
}
@After("pt()")
public void after() {
log.info("after ...");
}
@AfterReturning("pt()")
public void afterReturning() {
log.info("afterReturning ...");
}
@AfterThrowing("pt()")
public void afterThrowing() {
log.info("afterThrowing ...");
}
}
通知顺序
切入点表达式
execution
//切面类
@Slf4j
@Aspect
@Component
public class MyAspect6 {
//@Pointcut("execution(public void com.itheima.service.impl.DeptServiceImpl.delete(java.lang.Integer))")
//@Pointcut("execution(void com.itheima.service.impl.DeptServiceImpl.delete(java.lang.Integer))")
//@Pointcut("execution(void delete(java.lang.Integer))") //包名.类名不建议省略
//@Pointcut("execution(void com.itheima.service.DeptService.delete(java.lang.Integer))")
//@Pointcut("execution(void com.itheima.service.DeptService.*(java.lang.Integer))")
//@Pointcut("execution(* com.*.service.DeptService.*(*))")
//@Pointcut("execution(* com.itheima.service.*Service.delete*(*))")
//@Pointcut("execution(* com.itheima.service.DeptService.*(..))")
//@Pointcut("execution(* com..DeptService.*(..))")
//@Pointcut("execution(* com..*.*(..))")
//@Pointcut("execution(* *(..))") //慎用
@Pointcut("execution(* com.itheima.service.DeptService.list()) || " +
"execution(* com.itheima.service.DeptService.delete(java.lang.Integer))")
private void pt(){}
@Before("pt()")
public void before(){
log.info("MyAspect6 ... before ...");
}
}
@annotation
@annotation 切入点表达式,用于匹配标识有特定注解的方法。
连接点
在Spring中用JoinPoint抽象了连接点,用它可以获得方法执行时的相关信息,如目标类名、方法名、方法参数等。
对于 @Around 通知,获取连接点信息只能使用 ProceedingJoinPoint
对于其他四种通知,获取连接点信息只能使用JoinPoint,它是ProceedingJoinPoint 的父类型
//切面类
@Slf4j
@Aspect
@Component
public class MyAspect8 {
@Pointcut("execution(* com.itheima.service.DeptService.*(..))")
private void pt(){}
@Before("pt()")
public void before(JoinPoint joinPoint){
log.info("MyAspect8 ... before ...");
}
@Around("pt()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("MyAspect8 around before ...");
//1. 获取 目标对象的类名 .
String className = joinPoint.getTarget().getClass().getName();
log.info("目标对象的类名:{}", className);
//2. 获取 目标方法的方法名 .
String methodName = joinPoint.getSignature().getName();
log.info("目标方法的方法名: {}",methodName);
//3. 获取 目标方法运行时传入的参数 .
Object[] args = joinPoint.getArgs();
log.info("目标方法运行时传入的参数: {}", Arrays.toString(args));
//4. 放行 目标方法执行 .
Object result = joinPoint.proceed();
//5. 获取 目标方法运行的返回值 .
log.info("目标方法运行的返回值: {}",result);
log.info("MyAspect8 around after ...");
return result;
}
}
案例
步骤
准备:
在案例工程中引入AOP的起步依赖
导入资料中准备好的数据库表结构,并引入对应的实体类
编码:
自定义注解 @Log
定义切面类,完成记录操作日志的逻辑
获取当前登录用户
获取request对象,从请求头中获取到jwt令牌,解析令牌获取出当前用户的id。
实体类
接口方法
切面类
@Slf4j
@Aspect
@Component
public class LogAspect {
@Autowired
private OperateLogMapper operateLogMapper;
@Autowired
private HttpServletRequest request;
@Around("@annotation(com.itheima.anno.Log)")
public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable {
String jwt = request.getHeader("token");
Claims claims = JwtUtils.parseJWT(jwt);
Integer operateUser = (Integer)claims.get("id");
LocalDateTime operateTime= LocalDateTime.now();
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
String methodParams = Arrays.toString(args);
long begin = System.currentTimeMillis();
Object result=joinPoint.proceed();
long end = System.currentTimeMillis();
String returnValue = JSONObject.toJSONString(result);
Long costTime = end - begin;
OperateLog oprateLog= new OperateLog(null,operateUser,operateTime,className,methodName,methodParams,returnValue,costTime);
operateLogMapper.insert(oprateLog);
log.info("aop记录日志成功{}",oprateLog);
return result;
}
}
标签:info,log,void,SpringBootWeb,Pointcut,AOP,execution,public
From: https://blog.csdn.net/2403_85375987/article/details/142795709