学习笔记Spring中自定义注解
Posted 棉花糖灬
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习笔记Spring中自定义注解相关的知识,希望对你有一定的参考价值。
本文参考了文章@data注解_基础篇:深入解析JAVA注解机制和Spring项目中自定义注解的使用。
简单来说Spring中的自定义注解是基于AOP(面向切面编程)来实现的,即在一个方法的执行前后对其做修改,以新增一些功能。所以在看本文之前需要先了解AOP的相关知识。
1. 自定义注解类
新建Maven工程,创建注解类MyAnno
package ele.me;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnno {
// 注意是带小括号的
String value() default "";
int type() default 0;
}
上述代码中注解类上的三个注解称为自定义注解的元注解,自定义注解的元注解主要有以下五个:
- @Documented:注解信息会被添加到Java文档中,不常用
- @Retention:注解的生命周期,表示注解会被保留到什么阶段,其取值有3个:
SOURCE
:注解将被编译器丢弃,生成的class不包含注解信息CLASS
:注解在class文件中可用,但会被JVM丢弃;当注解未定义Retention值时,默认值是CLASSRUNTIME
:注解信息在运行期保留,可以通过反射机制读取注解的信息
- @Target:指定注解作用范围,可指定多个
TYPE
:适用范围:类、接口、注解类型,枚举类型enumFIELD
:作用于类属性 (includes enum constants)METHOD
:作用于方法PARAMETER
:作用于参数声明CONSTRUCTOR
:作用于构造函数声明LOCAL_VARIABLE
:作用于局部变量声明;
:作用于注解声明PACKAGE
:作用于包声明TYPE_PARAMETER
:作用于类型参数(泛型参数)声明TYPE_USE
:作用于使用类型的任意语句(不包括class)
- @Inherited:表示当前注解会被注解类的子类继承。即在子类Class 通过getAnnotations()可获取父类被@Inherited修饰的注解
- @Repetable:JDK1.8新加入的,表明自定义的注解可以在同一个位置重复使用
2. Controller方法应用注解
创建一个Controller,并将http请求映射到指定方法上
package ele.me;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class MyAnnoController {
@MyAnno(value = "MyAnno的value", type = 1)
@GetMapping("/myAnno/{id}")
@ResponseBody
public String myAnno(@PathVariable("id") Integer id) {
System.out.println("Controller执行,传入id为:" + id);
return "Success";
}
}
当上述代码没有添加@MyAnno注解时,在浏览器访问localhost:8080/myAnno/5
,控制台打印的内容为:Controller执行,传入id为:5
,浏览器页面显示的内容为Success
。
3. AOP方法定义注解功能
下面添加上@MyAnno注解并指定其value和type属性的值,利用AOP实现注解的功能
package ele.me;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class MyAnnoAOP {
@Pointcut("@annotation(MyAnno)")
private void pointcut(){}
@Around("pointcut() && @annotation(myAnno)")
public Object myAnnoAroundAdvice(ProceedingJoinPoint joinPoint, MyAnno myAnno) {
// 获取注解传来的参数
System.out.println("MyAnno.value: " + myAnno.value());
System.out.println("MyAnno.type: " + myAnno.type());
// 获取连接点的参数,即myAnno方法的id参数
Object[] args = joinPoint.getArgs();
// 将id的值变为原来的平方
for (int i = 0; i < args.length; i++) {
if (args[i] instanceof Integer) {
args[i] = (Integer)args[i] * (Integer)args[i];
}
}
Object result = null;
try {
// 调用原来的myAnno方法进行处理
result = joinPoint.proceed(args);
} catch (Throwable throwable) {
throwable.printStackTrace();
}
// 对myAnno方法的返回结果进行修改
if (result instanceof String) {
result += " aroundAdvice";
}
return result;
}
}
上面这段代码为@MyAnno注解添加了3个功能,一是打印添加注解时传来的value和type的属性值,我们可以根据传入参数值的不同进行不同的操作;二是将原来myAnno方法的入参id的值变为原来的平方;三是将原来myAnno方法的返回值加上字符串“ aroundAdvice”。
再在浏览器中访问相同的网页localhost:8080/myAnno/5
,控制台打印的内容为:Controller执行,传入id为:25
,浏览器页面显示的内容为Success aroundAdvice
。
以上是关于学习笔记Spring中自定义注解的主要内容,如果未能解决你的问题,请参考以下文章