在Java中实现一个简单的注解涉及以下几个步骤:
定义注解:使用@interface关键字定义一个注解接口。
添加元注解:使用元注解(如@Target和@Retention)来定义注解的作用域和生命周期。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// 定义注解的保留策略和目标元素类型
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) // 该注解应用于方法
public @interface SimpleAnnotation {
String value() default "default"; // 注解的元素,默认值为"default"
}
- 使用注解:在代码中使用你的自定义注解。
public class AnnotationExample {
// 在方法上使用自定义注解
@SimpleAnnotation(value = "Hello, Annotation!")
public void annotatedMethod() {
// 方法实现...
}
}
- 处理注解:通过反射在运行时读取和处理注解。
import java.lang.reflect.Method;
public class AnnotationProcessor {
public static void main(String[] args) throws Exception {
// 获取AnnotationExample类的Class对象
Class<?> clazz = AnnotationExample.class;
// 获取annotatedMethod方法的Method对象
Method method = clazz.getMethod("annotatedMethod");
// 通过反射获取方法上的SimpleAnnotation注解实例
SimpleAnnotation annotation = method.getAnnotation(SimpleAnnotation.class);
// 读取注解的值并打印
if (annotation != null) {
System.out.println(annotation.value());
}
}
}
注解本身是通过@interface关键字定义的一个特殊接口,使用反射API,如Class.getAnnotation()、Method.getAnnotation()等,可以获取到指定程序元素上的注解实例。当我们通过反射API获取注解时,实际上返回的是一个代理实例,这个代理实现了注解接口,并覆盖了接口中定义的所有方法。当我们调用这些方法时,代理会返回注解元素的值。注解处理器是能够读取、处理注解的程序,它们可以在编译时或运行时执行
下面自定义一个手机号码格式注解:
package com.example.seckilldemo.validator;
import com.example.seckilldemo.vo.IsMobileValidator;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(
validatedBy = {
IsMobileValidator.class
}
)
public @interface IsMobile {
//它表示是否必须验证这个字段或方法。默认值为 true,意味着通常需要验证。
boolean required() default true;
//定义了一个名为 message 的元素,它指定了当验证失败时返回的错误消息。默认消息是 "手机号码格式错误"
String message() default "手机号码格式错误";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
package com.example.seckilldemo.vo;
import com.example.seckilldemo.utils.ValidatorUtil;
import com.example.seckilldemo.validator.IsMobile;
import org.springframework.util.StringUtils;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class IsMobileValidator implements ConstraintValidator<IsMobile, String> {
private boolean required = false;
@Override
public void initialize(IsMobile constraintAnnotation) {
required = constraintAnnotation.required();
}
@Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
if (required) {
return ValidatorUtil.isMobile(s);
} else {
if (StringUtils.isEmpty(s)) {
return true;
} else {
return ValidatorUtil.isMobile(s);
}
}
}
}
IsMobile 是一个自定义的约束注解,用于验证手机号码格式是否正确。它通过 IsMobileValidator 类来进行实际的验证逻辑。当这个注解被用在Java代码中时,它可以提供声明式的验证,使得代码更加清晰,易于维护。