前面学习了如何自定义一个注解:java如何优雅的自定义一个注解 下面来实战演示一下如何使用自定义注解做一些实际的功能。比如校验对象属性是否为空。
一、自定义一个NotNull注解
我们自定义一个NotNull注解,里面有一个参数message 默认为“”;
/**
* 自定义注解
* 判断屬性不为空注解
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface NotNull {
/**
* 如果字段有该注解,判断为空并返回异常信息
*/
String message() default "";
}
二、创建实体对象Student
创建一个Student对象,有两个属性name、age,并给属性设置刚才自定义的NotNull 注解,
可以设置message信息,也可不设置。
package com.example.demo1.annotation;
/**
* 学生
* create by c-pown on 2020-07-03
*/
public class Student {
@NotNull
private String name;
@NotNull(message = "age is null")
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
三、解析校验Student对象
创建checkUserFiled方法校验对象属性是否为空,如果有使用NotNull注解的属性为空,则抛出异常。如果没有使用NotNull注解则不校验。
- Class<?> aClass = t.getClass();传入对象class。
- Field[] declaredFields = aClass.getDeclaredFields();获取当前对象所有属性 使用带
Declared
的方法可访问private属性 - 遍历对象属性Field
- field.setAccessible(true);开启访问权限,如果不设置,无法访问private注解。
- Object o = field.get(t);使用此方法 field.get(Object obj) 可以获取 当前对象这个属性的值
- Annotation annotation = field.getDeclaredAnnotation(NotNull.class);获取NotNull注解。如果没有设置当前注解 不用校验
- 校验注解。
package com.example.demo1.annotation;
import org.apache.commons.lang3.StringUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
/**
* 校验对象属性是否为null
* create by c-pown on 2020-07-03
*/
public class AnnotationTest {
/**
* 判断类属性是否为空
* @param t
* @param <T>
* @throws RuntimeException
*/
public static <T> void checkUserFiled(T t) throws RuntimeException, IllegalAccessException {
if(null == t){
throw new RuntimeException("obj is null");
}
//获取class对象
Class<?> aClass = t.getClass();
//获取当前对象所有属性 使用带Declared的方法可访问private属性
Field[] declaredFields = aClass.getDeclaredFields();
//遍历对象属性
for (Field field : declaredFields) {
//开启访问权限
field.setAccessible(true);
//使用此方法 field.get(Object obj) 可以获取 当前对象这个列的值
Object o = field.get(t);
Annotation annotation = field.getDeclaredAnnotation(NotNull.class);
//如果没有设置当前注解 不用校验
if(annotation == null){
continue;
}
//获取注解接口对象
NotNull notNull = (NotNull)annotation;
//如果设置了当前注解,但是没有值,抛出异常
if(o == null){
if(StringUtils.isNotBlank(notNull.message())){
//设置了注解message值 直接返回
throw new RuntimeException(notNull.message());
}else{
//没有设置可以拼接
throw new RuntimeException(field.getName()+" is null");
}
}
}
}
}
测试:
public static void main(String[] args) {
Student student = new Student();
// student.setName("张三");
// student.setAge(18);
try {
checkUserFiled(student);
} catch (IllegalAccessException e) {
e.printStackTrace();
}catch (RuntimeException e){
e.printStackTrace();
}
System.out.println(student);
}
设置name属性部位空,age为空。
Student student = new Student();
student.setName("张三");
// student.setAge(18);
全部设置:
Student student = new Student();
student.setName("张三");
student.setAge(18);
没有问题的。
使用反射可以对注解信息进行解析,在通过初始化调用可以对注解信息进行校验。实现注解的功能性。