Java 注解可以看做是 Javadoc 和 Xdoclet 标签的延伸和发展,我们可以自定义注解标签,并通过 Java 语言的反射机制来获取类中标注的注解,完成特定的功能 。
注解是代码的附属信息,无论增加还是删除注解,都不会影响程序代码的运行。因为 Java 语言解释器会忽略这些注解,而让第三方工具负责对注解进行处理 。 第三方工具可以利用代码中的注解间接控制程序代码的运行,它们通过 Java 反射机制读取注解的信息,并根据这些信息更改逻辑 。
1 定义
我们使用 @interface
来定义注解类。
示例:
@Retention(RetentionPolicy.RUNTIME)//保留期限
@Target(ElementType.METHOD)//目标类型
public @interface Log {
boolean value() default true;//声明成员变量
}
示例中的 @Retention
与 @Target
被称为元注解(Meta-annotation)。
1.1 成员变量
可以在注解类中定义多个成员变量,成员变量的定义语法有以下这些要求:
- 不能定义入参。
- 不能抛出异常。
- 可以通过 default 定义一个默认值。
- 合法的成员类型有这些 - 原始类型及其封装类、Class、enums、注解类型和包含上述类型的数组类型。
- 如果注解类只有一个成员变量,那么必须名为
value()
。在使用时可以忽略成员名称和赋值符号(=
),比如可以这样使用示例中的注解@Log(true)
。 - 如果注解类拥有多个成员变量,如果仅对 value 进行赋值,则也可以忽略成员名称和赋值符号(
=
)。 - 如果注解类拥有多个成员变量,又需要同时对多个成员变量进行赋值,那么就必须使用成员名称加赋值号表示,比如事务注解:
@Transactional(propagation= Propagation.MANDATORY,isolation= Isolation.DEFAULT)
。 - 注解类可以没有成员变量,这样注解类被称为标注注解,由调用程序负责判断处理。
- 注解类不能继承其它类,也不能实现其它接口。
1.2 保留期限 @Retention
@Retention
表示保留期限,它被定义在 java.lang.annotation.RetentionPolicy 中:
保留期限类型 | 说明 |
---|---|
SOURCE | 注解信息仅保留在源代码文件中。 |
CLASS | 注解信息保留在源代码文件与字节码文件中。 |
RUNTIME | 注解信息不仅保留在源代码文件与字节码文件中,而且会被加载到 JVM 中,在运行期可以通过反射读取这些注解信息。 |
1.3 目标类型 @Target
@Target
表示注解的应用目标类型。它被定义在 java.lang.annotation.ElementType 中。
目标类型 | 说明 |
---|---|
TYPE | 类、接口、注解类型、Enum 处声明。 |
FIELD | 成员变量、Enum 常量处声明。 |
METHOD | 方法处声明。 |
PARAMETER | 参数处声明。 |
CONSTRUCTOR | 构造函数处声明。 |
LOCAL_VARIABLE | 局部变量处声明。 |
ANNOTATION_TYPE | 注解类处声明。 |
PACKAGE | 包处声明。 |
TYPE_PARAMETER | 类型参数处声明。(1.8 新增) |
TYPE_USE | 使用类型处声明。(1.8 新增) |
2 配置注解
public class User {
@Log()
public void rent(String userId) {
System.out.println("User:租赁【充电宝】");
}
@Log(false)
public void back(String userId){
System.out.println("User:归还【充电宝】");
}
}
这里直接在需要的方法上,加入注解类。
标注注解的格式为:
@<注解名>(<成员名1>=<成员值1>,<成员名2>=<成员值2>,...)
如果成员变量是数组类型,就可以通过{}
进行赋值。
说明 | 示例 |
---|---|
单成员注解 | @Service("userService") |
多成员注解 | @Transactional(propagation= Propagation.MANDATORY,isolation= Isolation.DEFAULT) |
无成员注解 | @Override |
成员类型为普通数组 | @SuppressWarnings(value={"unchecked", "rawtypes"}) |
成员类型为注解数组 | @ComponentScans({@ComponentScan("1.xml"),@ComponentScan("2.xml")}) |
3 获取注解
对于保留期限为 RetentionPolicy.RUNTIME
的注解,可以通过反射来获取注解信息 。
在 Java5.0 中, Package、Class、Constructor、Method 以及 Field 等反射对象都新增了访问注解的多种方法,它们都支持泛型。
Class clazz = User.class;
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
//获取注解
Log log = method.getAnnotation(Log.class);
if (log != null) {
if (log.value()) {
System.out.println(method.getName() + "() 方法需要记录日志");
} else {
System.out.println(method.getName() + "() 方法不需要记录日志");
}
}
}
输出结果:
back() 方法不需要记录日志
rent() 方法需要记录日志
是不是很简单呀 O(∩_∩)O哈哈~
网友评论