/**
* 系统日志注解
*
* @author Mark sunlightcs@gmail.com
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {
String value() default "";
}
在上述自定义注解中我们发现有三个元注解@Target,@Retention,@Document,但是我们并不知道他们分别代表什么样的含义,接下来我们就详细的解释一下这三个元注解到底如何去使用他们 ?
1:@Target
当标记@Target这个注解就代表这个注解可以应用于那种的java元素类型
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
*指示注释类型适用的上下文。 的
*声明上下文和类型上下文,其中注释类型可能是
*适用于JLS 9.6.4.1中指定,并在源代码中用enum表示
*返回注释类型的元素数组
*可以适用。
*@返回注释类型的元素数组
*可应用于
ElementType[] value();
}
从@Target的源码可以看到。ElementType[] 这个枚举类数组
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
/** *用于描述类、接口(包括注解类型) 或enum声明,*/
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.METHOD) 表示只能在方法上声明
在比如:@Target(ElementType.TYPE_PARAMETER) 表示标注类型的参数
如下例子:
@Target(ElementType.TYPE_PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface TypeParameterAnnotation {
}
表示该注解@TypeParameterAnnotation 可以用于 泛型声明出
// 如下是该注解的使用例子 用于泛型出
public class TypeParameterClass<@TypeParameterAnnotation T> {
public <@TypeParameterAnnotation U> T foo(T t) {
return null;
}
}
在@Target注解中 ElementType.TYPE_USE包含了ElementType.TYPE和ElementType.TYPE_PARAMETER
package org.springmorning.demo.javabase.annotation.meta;
/**
* @author 春晨
* Copyright ©2019 春晨 https://www.cnblogs.com/springmorning/p/10264624.html
*/
import java.util.ArrayList;
//泛型类型声明时,使用TYPE_USE类型,编译通过
class A <@NotNull TT>{}
//泛型类型声明时,使用使用TYPE_PARAMETER类型,编译通过
public class TypeParameterAndTypeUseAnnotation<@NotEmpty T>{
//使用TYPE_PARAMETER类型,会编译不通过
// public @NotEmpty T test(@NotEmpty T a){
// new ArrayList<@NotEmpty String>();
// return a;
// }
//使用TYPE_USE类型,编译通过
public @NotNull T test(@NotNull T a){
new ArrayList<@NotNull String>();
return a;
}
}
@Retention 元注解 注解标记其他的注解用于指明标记的注解保留策略
从源代码的看到
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
定义元注解@Retention定义的数据是RetentionPolicy枚举值数组
/**
* Annotation retention policy. The constants of this enumerated type
* describe the various policies for retaining annotations. They are used
* in conjunction with the {@link Retention} meta-annotation type to specify
* how long annotations are to be retained.
*
* @author Joshua Bloch
* @since 1.5
*/
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文件中存在,但是在运行时,不会被VM保留。
*/
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.
*表示不仅会在编译后的class文件中存在,而且在运行时保留,因此它们主要用于反射场景,可以通过getAnnotation方法获取
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
首先要明确生命周期长度 SOURCE < CLASS < RUNTIME ,所以前者能作用的地方后者一定也能作用。
一般如果需要在运行时去动态获取注解信息,那只能用 RUNTIME 注解,比如@RestController使用RUNTIME注解
如果要在编译时进行一些预处理操作,比如生成一些辅助代码(如 ButterKnife),就用 CLASS注解;
如果只是做一些检查性的操作,比如 @Override 和 @SuppressWarnings,使用SOURCE 注解。
注解@Deprecated,用来表示某个类或属性或方法已经过时,不想别人再用时,在属性和方法上用@Deprecated修饰
如:
@RestController
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
* @since 4.0.1
*/
@AliasFor(annotation = Controller.class)
String value() default "";
}
我们可以使用javap -verbose class文件去分析可以看到自己定义的注解,当标记RUTINE那么在运行时是可以看到注解里面包含的参数
如果采用声明时采用的保留策略是CLASS,在运行时是看不到参数的
@Documented注解标记的元素,Javadoc工具会将此注解标记元素的注解信息包含在javadoc中。默认,注解信息不会包含在Javadoc中。示例如下:
声明Book注解,并使用@Document标记:
package org.springmorning.demo.javabase.annotation.meta;
import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
/**
* @author 春晨
* Copyright ©2019 春晨 https://www.cnblogs.com/springmorning/p/10261472.html
*/
@Documented
@Inherited
public @interface Book {
//书名
String name();
//出版日期
String publishedDate();
//作者
String author();
}
使用@Book注解标记类DocumentAnnotation,Book标记元素内容如下:
package org.springmorning.demo.javabase.annotation.meta;
/**
* @author 春晨
* Copyright ©2019 春晨 https://www.cnblogs.com/springmorning/p/10261472.html
*/
@Book(
name = "Spring in Action",
author = "Craig Walls",
publishedDate = "2008-10-1"
)
public class DocumentAnnotation {}
打开cmd 输入javadoc命令:
javadoc -d D:\doc org.springmorning.demo.javabase.annotation.meta -encoding utf-8 -charset utf-8
说明:
-d D:\doc 表示:doc文件输入目录为D盘的doc文件夹;
org.springmorning.demo.javabase.annotation.meta 表示此包中所有类需要生成java doc html文件;
-encoding utf-8 表示:java代码采用的是utf-8字符编码编写的;
-charset utf-8 表示:java doc html文件为utf-8字符编码。
再生成的java.doc文件 可以看到被@Document修饰的话都可以在java.doc文档中看的到
参考博客:
https://www.cnblogs.com/springmorning/p/10261472.html
https://www.cnblogs.com/springmorning/p/10265030.html