注解本质就是继承了Annotation的特殊接口,具体实现类为java运行是生产的动态代理类;(通过反射获取注解信息,然后通过java运行生成的动态代理类对象$Proxy1调用。通过代理对象调用自定义注解(接口)的方法。 并最终调动AnnotationInvocationHandler的invoke()。并从java的常量池
memberValues()中获取对应的值,从而获取到注解信息。
一、注解分类
注解解决了什么问题呢?在不影响业务代码逻辑下,利用语言特性,类似标记方式在编辑器编译前进行格式检查,编译后加载class文件初始化数据,或者在运行过程中动态加载相关配置等。
1. 元注解
基础注解,专门注解其他的注解。
@Documented – 注解是否将包含在JavaDoc中, 一个简单的Annotations 标记注解,表示是否将注解信息添加在java 文档中
@Retention – 什么时候使用该注解,譬如 @Override, @SuppressWarnings都属于这类注解
@Target – 注解用于什么地方,通过定义枚举类型来约束注解使用范围。
可用的ElementType 参数包括
● ElementType.CONSTRUCTOR: 用于描述构造器
● ElementType.FIELD: 成员变量、对象、属性(包括enum实例)
● ElementType.LOCAL_VARIABLE: 用于描述局部变量
● ElementType.METHOD: 用于描述方法
● ElementType.PACKAGE: 用于描述包
● ElementType.PARAMETER: 用于描述参数
● ElementType.TYPE: 用于描述类、接口(包括注解类型) 或enum声明
@Inherited – 是否允许子类继承该注解, @Inherited 阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited 修饰的annotation 类型被用于一个class,则这个annotation 将被用于该class 的子类。
2. 标准Annotation
也是常用到注解,譬如子类覆盖父类方法
常用@ Override注解,标记在方法上面, 被标注的方法重写了父类的方法,起到了断言的作用。如果我们使用了这种注解在一个没有覆盖父类方法的方法时,java 编译器将以一个编译错误来警示。
Deprecated
标记类型注解,
当一个类型或者类型成员使用@Deprecated 修饰的话,编译器将不鼓励使用这个被标注的程序元素。所以使用这种修饰具有一定的“延续性”:如果我们在代码中通过继承或者覆盖的方式使用了这个过时的类型或者成员,虽然继承或者覆盖后的类型或者成员并不是被声明为@Deprecated,但编译器仍然要报警。
SuppressWarning 不是一个标记类型注解,
它有一个类型为String[] 的成员,这个成员的值为被禁止的警告名。对于javac 编译器来讲,被-Xlint 选项有效的警告名也同样对@SuppressWarings 有效,同时编译器忽略掉无法识别的警告名。例如
@SuppressWarnings("unchecked")
3. 自定义注解
Annotation定义为@interface来定义自定义注解,并根据业务需求定义注解实现配置管理及标记等。
二、自定义注解
1. 自定义注解约束
a)通过@interface来定义,所以Annotation会自动继承java.lang.Annotation接口,并且无法继承其他的类和接口
b)访问修饰符只能为public和默认default
c)类型支持受限,只支持8种基本的数据类型
byte、short、char、int、long、float、double、boolean和
String、Enum、Class、annotations等数据类型,以及这一些类型的数组
d)
要获取类方法和字段的注解信息,必须通过Java的反射技术来获取 Annotation 对象,因为你除此之外没有别的获取注解对象的方法
e)
自定义注解需要使用到元注解
2.场景实例
a)类属性加入注解
####定义注解
@Target(FIELD)
@Retention(RUNTIME)
@Documented
public @interface
FieldName{
String value() default "";
}
####注解引用
@FieldName("FieldName")
private String fieldName;
b)注解自定义实例
package com.Cctiming.study.annotation;
import com.Cctiming.study.annotation.documented.CctimingDocumented;
import com.Cctiming.study.annotation.inherited.CctimingInherted;
import com.Cctiming.study.annotation.retention.CctimingRetentionRuntime;
import com.Cctiming.study.annotation.target.CctimingTargetConstructor;
import com.Cctiming.study.annotation.target.CctimingTargetField;
import com.Cctiming.study.annotation.target.CctimingTargetLocalVariable;
import com.Cctiming.study.annotation.target.CctimingTargetMethod;
import com.Cctiming.study.annotation.target.CctimingTargetParameter;
import com.Cctiming.study.annotation.target.CctimingTargetType;
/**
* @author timing
* @date 2022年8月18日 11:12:00
*
*/
@CctimingTargetType
@CctimingDocumented
@CctimingInherted
@CctimingRetentionRuntime
public class AnnotationDemo {
@CctimingTargetField
private String userName;
/**
* @description 这是一个构造方法!
* @see this constructor
* @param userName
*/
@CctimingTargetConstructor
public AnnotationDemo(@CctimingTargetParameter String userName){
this.userName=userName;
}
/**
*
*
*/
@CctimingTargetMethod
public void sayHello(){
@CctimingTargetLocalVariable
String info="userName : "+userName;
System.out.println(info);
}
public static void main(String[] args) {
AnnotationDemo demo=new AnnotationDemo("andy");
demo.sayHello();
}
}