java自定义注解(Annotation)实现属性隐藏-简单易懂小demo

631 阅读3分钟

「这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战

前言

今天在实现json返回数据时,要屏蔽掉其中的几个属性,于是我在网上查找了一下资料,只需要在相应的属性上加上@JsonIgnore注解就可以了,或者还有一种是在实体类上加上@JsonIgnoreProperties(value={"status","updateTime"}) 其中value里为要屏蔽的属性列表,我一看,这好使啊,前提是需要引入fastjson

Fastjson 是一个 Java 库,可以将 Java 对象转换为 JSON 格式,也可以将 JSON 字符串转换为 Java 对象。

所以我很好奇为什么一个注解就可以实现属性的屏蔽,对于java自定义注解,以前根本没用过,所以都不知道它的含义。

我打开@JsonIgnore源代码一看,这啥呀,就这样就能实现了吗?这什么也没有啊,于是我就去学习自定义注解了。

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonIgnore {
    boolean value() default true;
}

写了一个小demo

使用自定义注解实现属性屏蔽

首先定义一个学生类Student

public class Student {
    private String name;
    private int age;
    private BigDecimal account;

    public Student(){

    }
    public Student(String name, int age, BigDecimal account) {
        this.name = name;
        this.age = age;
        this.account = account;
    }
    //省略getter setter

}

注解类IgnoreFiled

@Target({ElementType.FIELD}) 
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoreFiled {

}

测试类:


public class Test {
    public static void main(String[] args) throws IllegalAccessException {
        Student student = new Student("张三",18, BigDecimal.valueOf(10000));
        printIgnoreField(student);
    }


    public static void printIgnoreField(Object obj) throws IllegalAccessException {
        StringBuilder builder = new StringBuilder();
        Class<?> c = obj.getClass();
        Field[] fields = c.getDeclaredFields();
        String[] className = c.getName().split("\.");
        builder.append(className[className.length-1]).append("{");
        for(Field field:fields){ //遍历属性
            field.setAccessible(true);
            if(!field.isAnnotationPresent(IgnoreFiled.class)){ //如果属性上没有IgnoreFiled这个注解类,拼接字符串
                builder.append(field.getName()).append("='").append(field.get(obj)).append("'").append(",");
            }
        }
        //删掉最后一个逗号
        builder.delete(builder.length()-1,builder.length());
        builder.append("}");
        System.out.println(builder);
    }
}

我们没有在对象属性上加**@IgnoreFiled**注解前

b0bece3c241f220c8e06576743603d5d.png

我们在account属性上加上注解

265d8af4ab0d732079c1c3f08c08b82e.png

输出

5306a685c43fba7167190793d0f1c6a8.png

是不是很简单也很容易懂

demo说明

首先我们看自定义的注解

@Target({ElementType.FIELD}) 
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoreFiled {
}
  • @Target说明了Annotation所修饰的对象范围:在Annotation类型的声明中使用了target可更加明晰其修饰的目标,取值如下:

    1.CONSTRUCTOR:用于描述构造器 2.FIELD:用于描述域 3.LOCAL_VARIABLE:用于描述局部变量 4.METHOD:用于描述方法 5.PACKAGE:用于描述包 6.PARAMETER:用于描述参数 7.TYPE:用于描述类、接口(包括注解类型) 或enum声明

  • @Retention定义了该Annotation的生命周期,就是在什么时候有效,取值如下:

    1.SOURCE:在源文件中有效(即源文件保留) 2.CLASS:在class文件中有效(即class保留) 3.RUNTIME:在运行时有效(即运行时保留)

  • @Documented – 注解是否将包含在JavaDoc中

  • @Inherited – 是否允许子类继承该注解,如果一个使用了@Inherited 修饰的annotation 类型被用于一个class,则这个annotation 将被用于该class 的子类。

然后通过反射获取Student类的属性,判断哪些属性上有我们自定义的注解,有的就不拼接,没有就拼接输出。

自定义注解的场景有很多,比如登录、权限拦截、日志、以及各种框架,常与切面编程结合,奈何我比较菜,今天的分享先到这里,每天进步一点点,相信会有质变的一天。