Annotation注解
上节介绍的反射似乎很厉害,可以在运行时操作和修改对象的行为,但是要使用反射,最起码要知道待反射的类所在的包路径和类名。所以项目中我们必须记录哪些类是需要反射进行获取的。
标记类信息的方式有如下几种:
-
XML方式保存类相关信息:
<bean id="welcomeService" class="cn.com.yuns.service.impl.WelcomeServiceImpl"/>
-
用注解来保存类相关信息
@Service public class JybWechatService implements IJybWechatService {
注解
提供一种为程序元素设置元数据的方法,什么是所谓的元数据?就是数据的数据即对数据的一种描述
- 元数据是添加到程序元素如方法,字段,类和包上的额外信息。
- 注解是一种分散式的元数据设置方式,XML是集中式的设置方式
- 注解不能直接干扰程序代码的运行。
总的来说:注解就是将我们需要的数据存储起来,在以后的某一时刻去使用,可能是编译时也可能是运行时。
所有注解均继承自Annotation这个接口。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface TestAnnotation {
}
但是我们看注解里面没有体现继承自Annotation这个接口,怎样才能看到呢?
首先需要执行 javac com/yuns/demo/annotation/TestAnnotation.java 命令将.java文件编译为.class文件,然后使用命令
javap -verbose com/yuns/demo/annotation/TestAnnotation 命令将.class文件反编译出来,我们可以看见反编译出来的类信息中就有接口继承自Annotation的信息:
Classfile /Users/wsq/Documents/demo/simpleframework/src/main/java/com/yuns/demo/annotation/TestAnnotation.class
Last modified 2020-6-23; size 405 bytes
MD5 checksum b830500c3cccd0ce2cbaaba7c81d3196
Compiled from "TestAnnotation.java"
public interface com.yuns.demo.annotation.TestAnnotation extends java.lang.annotation.Annotation
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
Constant pool:
#1 = Class #14 // com/yuns/demo/annotation/TestAnnotation
#2 = Class #15 // java/lang/Object
#3 = Class #16 // java/lang/annotation/Annotation
#4 = Utf8 SourceFile
#5 = Utf8 TestAnnotation.java
#6 = Utf8 RuntimeVisibleAnnotations
#7 = Utf8 Ljava/lang/annotation/Target;
#8 = Utf8 value
#9 = Utf8 Ljava/lang/annotation/ElementType;
#10 = Utf8 METHOD
#11 = Utf8 Ljava/lang/annotation/Retention;
#12 = Utf8 Ljava/lang/annotation/RetentionPolicy;
#13 = Utf8 SOURCE
#14 = Utf8 com/yuns/demo/annotation/TestAnnotation
#15 = Utf8 java/lang/Object
#16 = Utf8 java/lang/annotation/Annotation
{
}
SourceFile: "TestAnnotation.java"
RuntimeVisibleAnnotations:
0: #7(#8=[e#9.#10])
1: #11(#8=e#12.#13)
注解的功能:
- 作为特定的标记,告诉编译器一些信息 帮助编译器做一些语法检查 如:@Override,
- 程序编译时动态处理,如动态生成代码:如@data
- 程序运行时动态处理,作为额外信息的载体,如获取注解信息,(这个是重点),获取注解后获取各种信息
简单来说注解只是一种特殊的注释,如果没有解析它的代码,它可能连注释都不如。
注解的分类
- 标准注解:Override(重写),Deprecated(表示不再维护,有风险,不鼓励使用),SuppressWarnings(表示需要忽略某项Warning)
- 元注解(注解的注解):@Retention,@Target,@Inherited,@Documented
- 自定义注解:根据业务需要定义的注解(定义和元注解息息相关,自定义注解是使用元注解来定义的)
元注解
用于修饰注解的注解,通常用在注解的定义上;
Java中的元注解
-
@Target :指定注解的作用,目标
被描述的注解可以被用在什么地方:
packages,types(类,接口,枚举,Annotation类型)
类型成员(方法,构造方法,成员变量,枚举值)
方法参数和本地变量(循环变量,catch参数)
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 }
TYPE:
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Controller {
FIELD
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Autowired {
METHOD
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented @RequestMapping(method = RequestMethod.DELETE) public @interface DeleteMapping {
PARAMETER
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestBody {
-
@Retention:指定注解的生命周期
没描述的注解在什么范围内有效
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
* 被描述的注解在原文件中保留,但是在编译后的class文件中去除
*/
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
}
SOURCE
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface TestAnnotation {
}
public class HpMouse implements Mouse {
@Override
@TestAnnotation
public void sayHi() {
System.out.println("我是惠普鼠标");
}
}
javac com/yuns/demo/pattern/factory/entity/HpMouse.java 编译后:
package com.yuns.demo.pattern.factory.entity;
public class HpMouse implements Mouse {
public HpMouse() {
}
public void sayHi() {
System.out.println("我是惠普鼠标");
}
}
CLASS
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface TestAnnotation {
}
public class HpMouse implements Mouse {
@Override
@TestAnnotation
public void sayHi() {
System.out.println("我是惠普鼠标");
}
}
javac com/yuns/demo/pattern/factory/entity/HpMouse.java 编译后:
public class HpMouse implements Mouse {
public HpMouse() {
}
@TestAnnotation
public void sayHi() {
System.out.println("我是惠普鼠标");
}
}
RUNTIME
该类在运行时获得该注解的信息,运行时保留注解信息,程序可以在运行时通过反射来获取注解的信息
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
-
@Documented:指定直接是否应当被包含在JavaDoc文档中
加这个注解的注解会在生成的JavaDoc文档中出现注解
-
@Inherited:是否允许子类继承该注解
具有可继承性,注解修饰某个类,则该类的自类可以继承这个注解
网友评论