前置知识
@Aspect :表明是一个切面类
@Before :前置通知,在方法执行之前执行
@After :后置通知,在方法执行之后执行,不管是否有异常都会执行
@AfterRuturning :返回通知,在方法返回结果之后执行,有异常时获取不到返回值
@AfterThrowing :异常通知,在方法抛出异常之后执行
@Around :环绕通知,围绕着方法执行,包含上面四种通知
@Pointcut :切入点,方法或注解
实战
自定义注解TestMethod
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface TestMethod {
String value() default "testMethod";
}
自定义注解TestValue
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
public @interface TestVale {
String value() default "testValue";
}
切面
/**
* @author chenjun
* @Description
* 执行顺序:
* 环绕通知 --> 前置通知 --> 连接点 --> 后置返回通知/异常通知 --> 后置通知
* @create 2022-09-15 15:57
*/
@Aspect
@Component
@Slf4j
public class TestAspect {
@Pointcut("@annotation(com.cj.springboot.common.annotation.TestMethod)")
private void cutMethod() {
}
@Before("cutMethod()")
public void before(JoinPoint joinPoint) {
log.info("前置方法执行...");
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
//方法
Method method = methodSignature.getMethod();
//方法名
String methodName = method.getName();
//参数注解
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
for (Annotation[] parameterAnnotation : parameterAnnotations) {
for (Annotation annotation : parameterAnnotation) {
//方法参数上包含该注解
if (annotation instanceof TestVale) {
log.info("方法参数上匹配到TestValue注解");
}
}
}
Object[] args = joinPoint.getArgs();
Annotation[] annotations = args.getClass().getAnnotations();
for (Annotation annotation : annotations) {
//方法参数内部包含该注解
if (annotation instanceof TestVale) {
log.info("方法参数内部匹配到TestValue注解");
}
}
if (args.length > 0) {
Class<?> aClass = args[0].getClass();
Field[] declaredFields = aClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
if (declaredField.isAnnotationPresent(TestVale.class)) {
log.info("方法参数内部的字段匹配到TestValue注解");
declaredField.setAccessible(true);
}
}
}
}
/**
* 不管是否有异常都会执行
* @param joinPoint
*/
@After("cutMethod()")
public void after(JoinPoint joinPoint) {
log.info("后置方法执行...");
}
/**
* 发生异常时获取不到连接点的返回值
* @param point
* @param result
*/
@AfterReturning(value = "cutMethod()", returning = "result")
public void afterReturning(JoinPoint point, Object result) {
log.info("后置返回通知执行...:{}", result);
}
/**
* 异常通知方法只在连接点方法出现异常后才会执行,否则不执行
* @param point
* @param ex
*/
@AfterThrowing(value = "cutMethod()", throwing = "ex")
public void afterThrowing(JoinPoint point, Exception ex) {
log.info("后置异常通知执行...:{}", ex);
}
/**
* 环绕通知方法可以包含上面四种通知方法
* @param proceedingJoinPoint
* @return
*/
@Around(value = "cutMethod()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) {
log.info("环绕通知执行...");
try {
//执行目标方法
Object proceed = proceedingJoinPoint.proceed();
return proceed;
} catch (Throwable throwable) {
log.info("后置异常通知执行...:{}", throwable.getMessage());
}
return null;
}
}
实体类
@Data
@TableName("user")
public class User {
@TableId(type = IdType.AUTO)
private Integer id;
@TableField(value = "name")
@TestVale
private String name;
}
测试类
@RestController
@RequestMapping("/test")
public class TestAspectController {
@TestMethod
@GetMapping("test1")
public int test1(@TestVale User user) {
System.out.println("test1");
int a = 1 / 0;
return 1;
}
}
测试
结果
版权声明:本文为learning_chenjun原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。