SpringBoot 自定义注解使用

  1. 在SpringBoot的框架中,存在着许多的注解,每一个注解为我们减少了许多的代码,同时,在项目开发中,我们也可以像SpringBoot一样,使用属于自己的注解。
  2. @Target
    @Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。
public enum ElementType {
    /**用于描述类、接口(包括注解类型) 或enum声明 Class, interface (including annotation type), or enum declaration */
    TYPE,
 
    /** 用于描述域 Field declaration (includes enum constants) */
    FIELD,
 
    /**用于描述方法 Method declaration */
    METHOD,
 
    /**用于描述参数 Formal parameter declaration */
    PARAMETER,
 
    /**用于描述构造器 Constructor declaration */
    CONSTRUCTOR,
 
    /**用于描述局部变量 Local variable declaration */
    LOCAL_VARIABLE,
 
    /** Annotation type declaration */
    ANNOTATION_TYPE,
 
    /**用于描述包 Package declaration */
    PACKAGE,
 
    /**
     * 用来标注类型参数 Type parameter declaration
     * @since 1.8
     */
    TYPE_PARAMETER,
 
    /**
     *能标注任何类型名称 Use of a type
     * @since 1.8
     */
    TYPE_USE

列出一个例子

@Target(ElementType.TYPE_PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface TypeParameterAnnotation {
     
}
 
// 如下是该注解的使用例子
public class TypeParameterClass<@TypeParameterAnnotation T> {
    public <@TypeParameterAnnotation U> T foo(T t) {
        return null;
    }   
}

ElementType.TYPE_USE(Use of a type) 能标注任何类型名称,包括上面这个(ElementType.TYPE_PARAMETER的):

public class TestTypeUse {
 
    @Target(ElementType.TYPE_USE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface TypeUseAnnotation {
         
    }
     
    public static @TypeUseAnnotation class TypeUseClass<@TypeUseAnnotation T> extends @TypeUseAnnotation Object {
        public void foo(@TypeUseAnnotation T t) throws @TypeUseAnnotation Exception {
             
        }
    }
     
    // 如下注解的使用都是合法的
    @SuppressWarnings({ "rawtypes", "unused", "resource" })
    public static void main(String[] args) throws Exception {
        TypeUseClass<@TypeUseAnnotation String> typeUseClass = new @TypeUseAnnotation TypeUseClass<>();
        typeUseClass.foo("");
        List<@TypeUseAnnotation Comparable> list1 = new ArrayList<>();
        List<? extends Comparable> list2 = new ArrayList<@TypeUseAnnotation Comparable>();
        @TypeUseAnnotation String text = (@TypeUseAnnotation String)new Object();
        java.util. @TypeUseAnnotation Scanner console = new java.util.@TypeUseAnnotation Scanner(System.in);
    }
}
  1. @Retention
    定义注解的生命周期,分为以下三种
/*源码级别*/
// Annotations are to be discarded by the compiler.
SOURCE,
/*编译期级别*/
/*Annotations are to be recorded in the class file by the compiler,but need not be retained by the VM at run time.  This is the defaultbehavior.*/
CLASS,
/*运行期级别*/
/*Annotations are to be recorded in the class file by the compiler and retained by the VM at run time, so they may be read reflectively.
RUNTIME

注解@Retention可以用来修饰注解,是注解的注解,称为元注解。
Retention注解有一个属性value,是RetentionPolicy类型的,Enum RetentionPolicy是一个枚举类型,
这个枚举决定了Retention注解应该如何去保持,也可理解为Rentention 搭配 RententionPolicy使用。RetentionPolicy有3个值:CLASS RUNTIME SOURCE
按生命周期来划分可分为3类:
1、RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;
2、RetentionPolicy.CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期;
3、RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;
这3个生命周期分别对应于:Java源文件(.java文件) —> .class文件 —> 内存中的字节码。
那怎么来选择合适的注解生命周期呢?
首先要明确生命周期长度 SOURCE < CLASS < RUNTIME ,所以前者能作用的地方后者一定也能作用。
一般如果需要在运行时去动态获取注解信息,那只能用 RUNTIME 注解,比如@Deprecated使用RUNTIME注解
如果要在编译时进行一些预处理操作,比如生成一些辅助代码(如 ButterKnife),就用 CLASS注解;
如果只是做一些检查性的操作,比如 @Override 和 @SuppressWarnings,使用SOURCE 注解。

注解@Override用在方法上,当我们想重写一个方法时,在方法上加@Override,当我们方法的名字出错时,编译器就会报错
注解@Deprecated,用来表示某个类或属性或方法已经过时,不想别人再用时,在属性和方法上用@Deprecated修饰
注解@SuppressWarnings用来压制程序中出来的警告,比如在没有用泛型或是方法已经过时的时候

  1. @Documented
    Documented 注解表明这个注解应该被 javadoc工具记录. 默认情况下,javadoc是不包括注解的. 但如果声明注解时指定了 @Documented,则它会被 javadoc 之类的工具处理, 所以注解类型信息也会被包括在生成的文档中,是一个标记注解,没有成员。
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Column {
    public String name() default "fieldName";
    public String setFuncName() default "setField";
    public String getFuncName() default "getField"; 
    public boolean defaultDBValue() default false;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章