前言
(1)Java实现自定义注解其实很简单,跟类定义差不多,只是属性的定义可能跟我们平时定义的属性略有不同,这里会给大家详解,先来看代码:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomAnnotation {
String message() default "";
int[] nums();
}
上面代码就实现了一个自定义注解,实现自定义注解需要最少指定两个基本条件:①注解的作用范围②注解的生命周期,那这两个范围怎么指定呢?这个问题问的很好,指定这两个条件,就需要使用到了Java为我们提供的元注解(所谓的元注解:其实就是Java官网自己定义的注解,作用在注解上,并且为这个注解赋予了含义,当编译器扫描到这个注解时,就知道该注解是什么作用!)
(2)看到这里要注意的是,上面 message() 和 nums() 可能跟我们定义方法有点类似,但是,它不是方法!它不是方法!它不是方法!重要的事情讲三遍,它是java注解自定义属性的规则!(可能很多人疑惑也就是在这个点上!)
String message() default "";
上面表示的是定义一个 String 类型的 message属性,默认值为 ""
注解自定义属性的格式为: 属性类型 属性名称();
其中默认值可以写可以不写,如果需要给这个属性默认值,那么就使用 default 值 来为这个属性赋予默认值。这样就已经完成了自定义注解。
(3)刚才我们说过,需要自定义注解,最少指定两个基本条件:①注解的作用范围②注解的生命周期,那么就需要用到元注解,Java为我们提供了四个元注解,作用如下:
注解 | 作用 |
---|---|
@Target | 指定注解作用范围(比如说:该注解是作用在类上,还是方法,或者是属性上等等) |
@Retention | 指定注解的生命周期(也就是注解的保留时间,是在编译器有效,还是运行时有效等等) |
@Documented | 是一个标记注解,里面没有任何属性,用 @Documented 注解修饰的注解类会被 JavaDoc 工具提取成文档。(不常用,可选项) |
@Inherited | 也是一个标记注解,,没有定义属性,作用是为了表示该注解可以被继承(比如说:你自定义了一个A注解,并且使用了@Inherited修饰,然后在paren类使用了A注解,那么paren的所有子类都默认继承了注解A)。【不常用】 |
4)带大家看一下源码,看一下这几个元注解分别定义了哪些属性,并且有什么值:
①Target注解
可以看到,Target注解只是定义了一个Value属性,属性类型为 ElementType,来看一下ElementType有哪些值
public enum ElementType {
/** 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, //把该注解当做一个类型来使用
/**
* Module declaration.
*
* @since 9
*/
MODULE
}
@Retention
Retention也是只定义了一个value属性,该属性类型为: RetentionPolicy,我们再一起看看Retention有哪些值可以选择:
public enum RetentionPolicy {
/**
* 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 default
* behavior.
*/
CLASS, //该注解被保留在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.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME //该注解生命周期在运行时
}
@Documented
可以看到,Documented注解只是一个标记注解,里面什么属性都没有声明,作用是:使用了该注解的类,会被 doc工具提取成参考文档
@Inherited
这个注解也是一个标记注解,表示该注解是可以被继承的
总结
以上就是Java注解自定义的全部过程了,注解出现为开发人员提供了很大的便利,从以前spring工程需要繁琐复杂的xml各种配置,到现在只需要在类上添加注解,其中的对比一用可知,这里的注解也可以充当理解为就是一个标识符,比如说在类上使用 @Component,那么springBoot容器启动的时候就可以知道该类需要加载到容器中。