Spring 自定义注解
JDK元注解规范
@Documented -注解是否将包含在JavaDoc中
@Retention -什么时候使用该注解(生命周期)
RetentionPolicy.SOURCE: 在变异阶段丢弃,这些注解在编译结束之后就不再有任何意义,所以不会写入到字节码中
RetentionPolicy.CLASS: 在类加载的时候丢弃,在字节码文件的处理中有用,注解默认使用方式
RetentionPolicy.RUNTIME: 始终不会丢弃,运行器也保留该注解,因此可以使用反射机制读取该注解的信息,自定义注解通常使用这个方式。
@Target -注解用于什么地方
ElementType.CONSTRUCTOR: 用于描述构造器
ElementType.FIELD: 用于描述变量,对象,属性
ElementType.LOCAL_VARIABLE: 用于描述局部变量
ElementType.METHOD:用于描述方法
ElementType.PACKAGE: 用于描述包
ElementType.PARAMETER: 用于描述参数
ElementType.TYPE: 用于描述类,接口
@Inherited -是否允许子类继承该注解
1.自定义注解 SayHello
本 注解用于方法上,入参helloValue默认 5000
/**
* @Author Christ @Date 2023/9/6 11:19 @Version 1.0
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SayHello {
int helloValue() default 5000;
}
2.注解切面
此处举例四个常用的切面处理
访问方法前 @Before
访问方法后 @After
访问方法拿到了返回值后 @AfterReturning
抛出异常后 @AfterThrowing
**
* @Author Christ @Date 2023/9/6 11:24 @Version 1.0
*/
@Aspect
@Component
public class SayHelloAspect {
/** 定义切点,切点为添加了注解的方法
* com.jlink.common.annotation.SayHello 注解路径
*/
@Pointcut("@annotation(com.christ.common.annotation.SayHello)")
public void aopPointCut() {}
@Before("aopPointCut()")
public void beforeHello(JoinPoint point) {
System.out.println("访问接口前--------------------------");
// 让我看看入参 有没有要验证
Object[] args = point.getArgs();
System.out.println(Arrays.toString(args));
// 获取当前方法签名
MethodSignature signature = (MethodSignature) point.getSignature();
// 反射机制获取注解
SayHello sayHello = signature.getMethod().getAnnotation(SayHello.class);
// 获取注解的值
int i = sayHello.helloValue();
System.out.println("想要访问我这个接口,那就对我说声hello吧! 注解入参:" + i);
}
@After("aopPointCut()")
public void afterHello(JoinPoint point) {
System.out.println("访问接口后--------------------------");
// 获取当前方法签名
MethodSignature signature = (MethodSignature) point.getSignature();
// 反射机制获取注解
SayHello sayHello = signature.getMethod().getAnnotation(SayHello.class);
// 获取注解的值
int i = sayHello.helloValue();
System.out.println("想要访问我这个接口,那就对我说声hello吧! 注解入参:" + i);
}
@AfterReturning(pointcut = "aopPointCut()", returning = "jsonResult")
public void afterHello(JoinPoint point, Object jsonResult) {
System.out.println("访问接口后拿到了返回值--------------------------");
// 看看返回值拿到了啥
System.out.println(jsonResult);
// 获取当前方法签名
MethodSignature signature = (MethodSignature) point.getSignature();
// 反射机制获取注解
SayHello sayHello = signature.getMethod().getAnnotation(SayHello.class);
// 获取注解的值
int i = sayHello.helloValue();
System.out.println("想要访问我这个接口,那就对我说声hello吧! 注解入参:" + i);
}
@AfterThrowing(pointcut = "aopPointCut()", throwing = "e")
public void afterHello(JoinPoint point, Exception e) {
System.out.println("访问接口后抛出了异常--------------------------");
// 看看返回值拿到了啥
System.out.println(e);
// 获取当前方法签名
MethodSignature signature = (MethodSignature) point.getSignature();
// 反射机制获取注解
SayHello sayHello = signature.getMethod().getAnnotation(SayHello.class);
// 获取注解的值
int i = sayHello.helloValue();
System.out.println("想要访问我这个接口,那就对我说声hello吧! 注解入参:" + i);
}
}
3.使用方法添加SayHello注解
(无异常情况)
@PostMapping("/login")
@SayHello(helloValue = 666) // 注解入参 666
public Map<String, Object> login(@RequestBody LoginBody loginBody) throws Exception {
Map<String, Object> ajax = new HashMap<>();
// 生成令牌
String token =
loginService.login(
loginBody.getUsername(),
loginBody.getPassword(),
loginBody.getCode(),
loginBody.getUuid());
ajax.put(Constants.TOKEN, token);
ajax.put("code", 200);
ajax.put("msg", "操作成功");
// throw new Exception();
return ajax;
}
打印日志
@Before(“aopPointCut()”)
@AfterReturning(pointcut = “aopPointCut()”, returning = “jsonResult”)
@After(“aopPointCut()”)
(有异常情况)
@PostMapping("/login")
@SayHello(helloValue = 666) // 注解入参 666
public Map<String, Object> login(@RequestBody LoginBody loginBody) throws Exception {
Map<String, Object> ajax = new HashMap<>();
throw new Exception();
}
打印日志
@AfterThrowing(pointcut = “aopPointCut()”, throwing = “e”)