JAVA中注解是怎么做到的(上)

电子说

1.2w人已加入

描述

概述

注解想必大家在项目中经常使用,比如Spring框架中常用的一些注解:@Controller@Service@RequestMapping等等,它是JDK1.5及以后版本引入的一个特性。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。那么你知道JDK什么是元注解吗?注解有哪些分类吗?以及注解在Java中最本质究竟是什么东西,是如何实现的呢?

注解的分类

根据注解的使用场景,主要分为三类,元注解、内置注解和自定义注解。

元注解

用于定义注解的注解,通常用于注解的定义上,标明该注解的使用范围、生效范围等。简而言之,元注解是用来修饰注解的。

@Retention

指定注解信息保留到哪个阶段,分别为源代码阶段、编译Class阶段、运行阶段。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}
  • SOURCE: 保留在源代码java中,被编译器丢弃,也就是说在class文件中不包含注解信息,通常用来标记源码,引起大家的注意,比如自定义一个注解例如@ThreadSafe,用来标识一个类时线程安全的。
  • CLASS: 编译后的class文件中包含注解信息,但是会被jvm丢弃
  • RUNTIME: 注解信息在运行期(JVM)保留(.class也有),可以通过反射机制读取注解的信息

@Target

指定注解的使用范围,如类、方法、属性、局部属性、参数等, 可以多选。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    /**
     * Returns an array of the kinds of elements an annotation type
     * can be applied to.
     * @return an array of the kinds of elements an annotation type
     * can be applied to
     */
    ElementType[] value();
}

具体可选的枚举如下:

public enum ElementType {
    /** 适用范围:类、接口、注解类型,枚举类型enum */
    TYPE,
    /** 作用于类属性 (includes enum constants) */
    FIELD,
    /** 作用于方法 */
    METHOD,
    /** 作用于参数声明 */
    PARAMETER,
    /** 作用于构造函数声明 */
    CONSTRUCTOR,
    /** 作用于局部变量声明 */
    LOCAL_VARIABLE,
    /** 作用于注解声明 */
    ANNOTATION_TYPE,
    /** 作用于包声明 */
    PACKAGE,
    /** 作用于类型参数(泛型参数)声明 */
    TYPE_PARAMETER,
    /** 作用于使用类型的任意语句(不包括class) */
    TYPE_USE
}

@Inherited

加上该注解的注解,表示可以被标注的类子类继承,比如A上标记了带有@Inherited的注解,那么类B继承了A, 那么B也会有这个注解,默认情况下注解是不支持继承的。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}

@Document

将此注解包含在 javadoc 中 ,它代表着此注解会被javadoc工具提取成文档。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}

@Repeatable

1.8中加入的元注解,用来标记是否可以重复标记。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Repeatable {
    /**
     * Indicates the containing annotation type for the
     * repeatable annotation type.
     * @return the containing annotation type
     */
    Class? extends Annotation value();
}

内置注解

java提供了一些内置注解,可以配合编译器来检查代码的正确性, 我们可以关注他们的元注解。

@Override

标记当前方法是覆写父类的方法。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

@Deprecated

标记一个元素为已过期,不要在使用了

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}

@SuppressWarnings

用来关闭编译器输出的警告信息

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    String[] value();
}

@FunctionalInterface

java8中引入,标记是一个函数式接口,也就是说有且只有一个抽象方法的接口

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}

自定义注解

注解遵循的格式一般如下:

//元注解部分 xxxx
@Retention(xxxx)
@Target(xxxx)
public @interface 注解名 {
  返回值 属性名() 默认值;
  返回值 属性名() 默认值;
}
  • 返回值支持的类型如下:java的8种基础类型(不支持包装类型)、String、Class、Enum、Annotation、以及上面类型的数组。
  • 默认值可选,非必有。

举个项目中自定义的栗子:

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented  
@Inherited
public @interface DataAuthorize {
    /**
     * 资产ID
     * @return
     */
    String assetId();

    /**
     * 资产类型
     * @return
     */
    String assetType();

    /**
     * 权限代码
     * @return
     */
    String authCode() default "";

    /**
     * 使用的类型
     * @return
     */
    Class[] useType();
}
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分