参考:
Java实现自定义注解_奔跑的大白啊的博客-CSDN博客_java自定义注解
一、正文
上一篇文章介绍了注解的一些基本知识,这次来介绍下如何实现自定义注解及注解如何使用。
注解是一种能被添加到java源代码中的元数据,方法、类、参数和包都可以用注解来修饰。注解可以看作是一种特殊的标记,可以用在方法、类、参数和包上,程序在编译或者运行时可以检测到这些标记而进行一些特殊的处理。
二、注解的作用
- 生成文档,根据文档注解,可以生成java文档
- 追踪代码依赖性,实现替代配置文件功能(最主要的功能)
- 在编译时进行格式检查,告知编译器哪些代码需要检查
三、注解的分类
1、按作用的生命周期分
- 源码注解:在源码时起作用,在编译时失效
- 编译时注解:在编译时起作用,在运行时失效
- 运行时注解:只在运行时起作用
2、按来源分
第一种:元注解
元注解就是用来定义注解的注解
- @Target : 是注解的作用域,表示该注解可以用于一个类中的那些属性及方法上,如果作用域类型有多个用英文逗号分隔(空间上的有效范围)
注:属性需要通过枚举类ElementType来引用,如ElementType.METHOD
- @Retention : 注解的生命周期,表明该注解在什么时候起作用,什么时候失效(时间上的有效范围)
注:上面的这些常量需要通过枚举类RetentionPolicy来引用,如RetentionPolicy.RUNTIME
- @Inherited:此注解是标识性的元注解,表示当前注解可以由子注解来继承
- @Documented:表示生成javadoc的时候会包含注解
第二种:普通注解
- @Override : 标记它覆盖了它的父类或接口的方法
- @Deprecated : 标记该方法或字段不再推荐使用
- @SuppviseWarning : 是否忽略过时的方法
由第三方类库或框架定义的注解,比如Spring中的注解@Controller
2.使用自定义注解
注:注解只是一种标记,如果不解析,它是不会实现任何功能的
使用元注解修饰注解
JDK中有一些元注解,主要有@Target,@Retention,@Document,@Inherited用来修饰注解。
@Target
表明该注解可以应用的java元素类型
@Retention
表明该注解的生命周期
@Document
表明该注解标记的元素可以被Javadoc 或类似的工具文档化
@Inherited
表明使用了@Inherited注解的注解,所标记的类的子类也会拥有这个注解
四、使用自定义注解
注:注解只是一种标记,如果不解析,它是不会实现任何功能的
定义标记需要使用元注解
- 使用元注解@Target来标记该注解的作用范围(空间范围,在哪些地方可以使用)
- 使用元注解@Retention来标记该注解的作用时间范围(时间范围,在什么时候起作用)
- 使用元注解@Inherited来标记该注解是否可以由子注解来继承
- 使用元注解@Documented来标记该注解是否需要自动生成文档
- 使用@interface关键词来定义注解
- 在注解内部定义一些相关的属性,一般是方法的形式来定义属性
package main.java.com.shixinke.java.demo.annotation;
import java.lang.annotation.*;
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Check {
boolean value() default false;
}
注:自定义注解本质上是继承自Annotation的类
(2)标记注解:打标,表明此处要使用此标记
定义一个User类,标记为@Check
package main.java.com.shixinke.java.demo.annotation;
@Check(true)
public class User {
}
定义一个Person类,不标记
package main.java.com.shixinke.java.demo.annotation;
public class Person {
}
(3)解析注解:扫描标记,实现功能
一般通过反射来实现扫描注解,并在解析器中实现功能:
那么注解我们写好了,具体怎么用呢?
1. isAnnotationPresent(annotation.class):判断该程序元素上是否包含指定类型的注解
2. getAnnotations():返回该程序元素上存在的所有注解。
3. getDeclaredAnnotations():返回直接存在于此元素上的所有注释。
- 注解解析器来解析注解并实现功能
package main.java.com.shixinke.java.demo.annotation;
import java.lang.annotation.Annotation;
public class CheckParser {
public void parse(Class cls) {
//判断注解是否生效
if (cls.isAnnotationPresent(Check.class)) {
//获取Check的注解对象
Annotation annotation = cls.getAnnotation(Check.class);
Check check = (Check) annotation;
System.out.println(cls.getName() + "在检查中........");
}
}
}
对于一个类或者接口来说,Class类(java.lang包下)中提供了一些方法用于反射注解,当然对于字段、方法来说反射注解的方式很类似。
//返回指定的注解
getAnnotation
//判断当前元素是否被指定注解修饰
isAnnotationPresent
//返回所有的注解
getAnnotations
- 调用注解解析器
package main.java.com.shixinke.java.demo.annotation;
public class AnnotationDemo {
public static void main(String[] args) {
User user = new User();
Person person = new Person();
CheckParser parser = new CheckParser();
parser.parse(user.getClass());
parser.parse(person.getClass());
}
}
运行结果:
//main.java.com.shixinke.java.demo.annotation.User在检查中........