注解的定义
Java注解用于为Java代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上是用于这一目的的。Java注解是从Java5开始添加到Java的。
注解即标签
注解就是为 类,接口,方法,属性等打上一个标签
如何自定义注解
1.通过@interface关键字定义
public @interface Test {
}
元注解:注解的注解,就是标签的标签
有5种:@Retention、@Document、@Target、@Inherited、@Repeatable
@Repeatable
java8新添加的,可重复的意思,被此注解注释的注解可以重复使用在一个对象
@Retention:
Retention的英文意思是保留期的意思。当@Retention应用到一个注解上的时候,它解释说明了这个注解的存活时间。
取值如下:
1.RetentionPolicy.SOURCR:注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视
2.RetentionPolicy.CLASS:注解只被保留到编译进行的时候,它并不会被加载到JVM中。
3.RetentionPolicy.RUNTIME:注解可以保留到程序运行的时候,他会保留到JVM中,所以在运行程序时可以获取到它们。
@Target
Target是目标的意思、@Target指定了注解运用的地方
当一个注解被@Target注解时,这个注解就被限定了运用场景。
举例:原本标签可以任意贴在认任何地方,但是被@Target注释的标签只能贴在指定范围内,比如类、方法、属性等。
取值如下:
/** 类、接口(包括注释类型)或enum声明 /
TYPE,
/字段声明(包括enum常量) /
FIELD,
/ 方法声明 /
METHOD,
/* 正式的参数声明,方法的参数进行注解/
PARAMETER,
/* 构造函数声明 /
CONSTRUCTOR,
/局部变量声明 /
LOCAL_VARIABLE,
/ 注释类型声明 /
ANNOTATION_TYPE,
/* 包声明/
PACKAGE,
/*
* 类型参数声明
* @since 1.8
/
TYPE_PARAMETER,
/*
*使用类型
* @since 1.8
*/
TYPE_USE
@Document
顾名思义,这个元注解肯定和文档有关,他的作用是能将注解的元素包含到Javadoc中去。ElementType.TYPE可以给一个类型进行注解,比如类、接口、枚举
@Inherited
Inherited是继承的意思,但是并不是说注解本身可以继承,而是说如果一个超类被@Inherited注解过的注解进行注解的话,那么如果它的子类没有被任何注解注释的话,那么这个子类就继承了超类的注解。
注解的属性
注解的属性也叫做成员变量。注解只有成员变量,没有方法。
在注解中定义属性时它的类型必须是8种基本数据类型外加类(Class)、接口、注解以及他们的数组,注解种的属性可任意有默认值,默认值需要用default 关键字指定
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test{
int id() default -1;
String msg() default "Hello";
}
注解的提取
运行期注解通过反射获取。首先可以通过 Class 对象的 isAnnotationPresent() 方法判断它是否应用了某个注解
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {}
然后通过 getAnnotation() 方法来获取 Annotation 对象。
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {}
或者是 getAnnotations() 方法。
public Annotation[] getAnnotations() {}
前一种方法返回指定类型的注解,后一种方法返回注解到这个元素上的所有注解。
如果获取到的 Annotation 如果不为 null,则就可以调用它们的属性方法了。比如
@Test()
public class TestDemo{
public static void main(String[] args) {
boolean hasAnnotation = TestDemo.class.isAnnotationPresent(Test.class);
if ( hasAnnotation ) {
TestAnnotation testAnnotation = TestDemo.class.getAnnotation(Test.class);
System.out.println("id:"+testAnnotation.id());
System.out.println("msg:"+testAnnotation.msg());
}
}
}
APT
注解的用处:
1.提供信息给编译器:编译器可以利用注解来探测错误和警告信息。(AS)
2.编译阶段时的处理:软件工具可以利用注解信息来生成代码、Html、文档或者做其他相应处理。(aapt2)
3.运行时的处理:某些注解可以在程序运行的时候接受代码的提取。(通过反射,应该有个工具在运行期间获取注解信息)
3个知识点:Java注解、java反射、依赖注入
依赖注入标准
@Inject
注解 @Inject
标识了可注入的构造器、方法或字段。可以用于静态或实例成员。一个可注入的成员可以被任何访问修饰符(private、package-private、protected、public)修饰。注入顺序为构造器,字段,最后是方法。超类的字段、方法将优先于子类的字段、方法被注入。对于
同一个类的字段是不区分注入顺序的,同一个类的方法亦同
Provider<T>
接口 Provider 用于提供类型 T 的实列。Provider 是一般情况是由注入器实现的。对于任何可注入的 T 而言,您也可以注入 Provider<T>。与直接注入 T 相比,注入 Provider<T> 使得:
- 可以返回多个实例。
- 实例的返回可以延迟化或可选
- 打破循环依赖。
- 可以在一个已知作用域的实例内查询一个更小作用域内的实例。
class Car {
@Inject Car(Provider<Seat> seatProvider) {
Seat driver = seatProvider.get();
Seat passenger = seatProvider.get();
…
}
}
- get()
用于提供一个完全构造的类型 T 的实例。
异常抛出:RuntimeException —— 当注入器在提供实例时遇到错误将抛出此异常。例如,对于一个可注入的成员 T
抛出了一个异常,注入器将包装此异常并将它抛给 get()
的调用者。调用者不应该尝试处理此类异常,因为不同注入器实现的行为不一样,即使是同一个注入器,也会因为配置不同而表现的行为不同。
@Qualifier
用于标识限定器注解。任何人都可以定义新的限定器注解。一个限定器注解:
- 是被 @Qualifier、@Retention(RUNTIME) 标注的,通常也被 @Documented 标注。
- 可以拥有属性。
- 可能是公共 API 的一部分,就像依赖类型一样,而不像类型实现那样不作为公共 API 的一部分。
- 如果标注了 @Target 可能会有一些用法限制。本规范只是指定了限定器注解可以被使用在字段和参数上,但一些注入器配置可能使用限定器注解在其他一些地方(例如方法或类)上。
@Named
- 基于 String 的[限定器]
@Scope
- 用于标识作用域注解。一个作用域注解是被标识在包含一个可注入构造器的类上的,用于控制该类型的实例如何被注入器重用。缺省情况下,如果没有标识作用域注解,注入器将为每一次注入都创建(通过注入类型的构造器)新实例,并不重用已有实例。如果多个线程都能够访问一个作用域内的实例,该实例实现应该是线程安全的。作用域实现由注入器完成。
@Singleton
- 标识了注入器只实例化一次的类型。该注解不能被继承
网友评论