在开发过程中我们看到过很多不同的注解,但是让你自己定义一个注解你会用吗?今天就来看看如何自定义一个注解。
Java注解(Annotation)又称Java标注,是JDK5.0引入的一种注释机制。Java语言中的类、方法、变量、参数和包等都可以被标注。和Javadoc不同,Java标注可以通过反射获取标注内容。在编译器生成类文件时,标注可以被嵌入到字节码中。Java虚拟机可以保留标注内容,在运行时可以获取到标注内容 。 当然它也支持自定义Java标注。我们来看下这几个注解的具体意思:
1、@Target定义注解的使用位置,用来标注注解的可以被声明在哪些元素之前
ElementType.TYPE声明在类、接口(包括注释类型)或枚举上
ElementType.FIELD声明在字段(包括枚举常量)
ElementType.METHOD声明在一个类的方法前
ElementType.PARAMETER声明在方法的参数前
ElementType.CONSTRUCTOR声明在一个类的构造方法前
ElementType.LOCAL_VARIABLE声明在一个局部变量前
ElementType.ANNOTATION_TYPE声明在一个注解类前
ElementType.PACKAGE声明在一个包名前
ElementType.TYPE_PARAMETER声明在类型参数前,开始于JDK1.8
ElementType.TYPE_USE能标注任何类型名称,开始于JDK1.8
2、@Retention用来定义注解类的生命周期
RetentionPolicy.SOURCE注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃
RetentionPolicy.CLASS注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期
RetentionPolicy.RUNTIME注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在,因此可以反射地读取它们
3、@Constraint通过validatedBy来指定验证器4、使用 @interface 定义注解时,意味着它实现了 java.lang.annotation.Annotation 接口,即该注解就是一个Annotation。定义 Annotation 时,@interface 是必须的。注意:它和我们通常的 implemented 实现接口的方法不同。Annotation 接口的实现细节都由编译器完成。通过 @interface 定义注解后,该注解不能继承其他的注解或接口。
1、统一依赖
org.springframework.boot
spring-boot-starter-web
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-aop
2、创建注解
/**
* 自定义注解
* @author RickSun && iFillDream
* @date 2020/02/09 12:57
* @Copyright "轻梦致新"即"iFillDream"公众号所有
*/
//声明在字段上
@Target(ElementType.FIELD)
//运行时注解,以便于反射获取
@Retention(RetentionPolicy.RUNTIME)
//关联验证器
@Constraint(validatedBy = CheckValidated.class)
public @interface CheckAnnotation {
//注解参数
String[] paramValues();
//错误提示
String message() default "参数错误";
Class>[] groups() default {};
Class extends Payload>[] payload() default {};
}
3、创建验证器
import com.ifilldream.test.test_lean.annotation.CheckAnnotation;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Arrays;
import java.util.List;
/**
* 验证器
* @author RickSun && iFillDream
* @date 2020/02/09 12:59
* @Copyright "轻梦致新"即"iFillDream"公众号所有
*/
public class CheckValidated implements ConstraintValidator {
//参数集合
private List paramList;
//初始化赋值
@Override
public void initialize(CheckAnnotation checkAnnotation){
paramList = Arrays.asList( checkAnnotation.paramValues() );
}
@Override
public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
if(paramList.contains(o)){
System.out.println("通过");
return true;
}
System.out.println("不通过");
return false;
}
}
4、创建请求Request:
/**
* 添加用户Request
* @author RickSun && iFillDream
* @date 2020/02/09 13:01
* @Copyright "轻梦致新"即"iFillDream"公众号所有
*/
@Data
public class AddUserRequest {
@CheckAnnotation(paramValues = {"filldream","iFillDream"})
private String name;
private Integer age;
}
5、测试类
/**
* 校验Controller
* @author RickSun && iFillDream
* @date 2020/02/09 13:03
* @Copyright "轻梦致新"即"iFillDream"公众号所有
*/
@RestController
@RequestMapping("/ifilldream/check")
public class CheckController {
@PostMapping
public String check(@Validated @RequestBody AddUserRequest addUserRequest) {
return "ok.";
}
}
测试通过则会打印出"通过"字样。
到此基本的自定义注解就讲解完毕了,还可以在方法、类中使用,可以结合拦截器和AOP使用。
统一首发平台为-微|信-*公|众-号"轻梦致新",搜索关注-公|众-**号,第一时间阅读最新内容。