一、元注解
元注解就是修饰注解的注解,是用于注解上的。常见的注解@Override注解定于如下:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
元注解有:
@Target:注解的作用目标
@Retention:注解的生命周期
@Documented:注解是否应当被包含在 JavaDoc 文档中
@Inherited:是否允许子类继承该注解
@Target定义:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
ElementType是一个枚举类型,有如下参数:
@Target(value = {ElementType.FIELD}) 赋值方式
ElementType.TYPE:允许被修饰的注解作用在类、接口和枚举上
ElementType.FIELD:允许作用在属性字段上
ElementType.METHOD:允许作用在方法上
ElementType.PARAMETER:允许作用在方法参数上
ElementType.CONSTRUCTOR:允许作用在构造器上
ElementType.LOCAL_VARIABLE:允许作用在本地局部变量上
ElementType.ANNOTATION_TYPE:允许作用在注解上
ElementType.PACKAGE:允许作用在包上
@Retention定义:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
RetentionPolicy value();
}
@Retention(value = RetentionPolicy.RUNTIME 赋值方式
RetentionPolicy 是一个枚举类型,它有以下几个枚举值可取:
RetentionPolicy.SOURCE:当前注解编译期可见,不会写入 class 文件
RetentionPolicy.CLASS:类加载阶段丢弃,会写入 class 文件
RetentionPolicy.RUNTIME:永久保存,可以反射获取
@Documented 注解修饰的注解,当我们执行 JavaDoc 文档打包时会被保存进 doc 文档,反之将在打包时丢弃。
@Inherited 注解修饰的注解是具有可继承性的,也就说我们的注解修饰了一个类,而该类的子类将自动继承父类的该注解。
二、自定义注解
@Target(ElementType.FIELD) //注解作用于属性上
@Retention(RetentionPolicy.RUNTIME) //运行时 源代码+字节码+运行
public @interface MyAnnotationField { //用@interface修饰
String value() default "自定义属性注解"; //z只有成员变量,变量是一个无参方法,可以有默认值 用default
/**
注解的属性可支持数据类型有如下:
1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)
2.String类型
3.Class类型
4.enum类型
5.Annotation类型
6.以上所有类型的数组
*/
}
自定义注解需要注册注解处理器进行解析:1.运行时反射 2.编译时直接扫描
三、注解处理器
对于一个类或者接口来说,Class 类中提供了以下一些方法用于反射注解:
getAnnotation:返回指定的注解
isAnnotationPresent:判定当前元素是否被指定注解修饰
getAnnotations:返回所有的注解
getDeclaredAnnotation:返回本元素的指定注解
getDeclaredAnnotations:返回本元素的所有注解,不包含父类继承而来的
例子如下:
package com.springboot.annotationRuntime;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Administrator
* @description 自定义注解
* @date 2019/12/31
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotationField {
String value() default "自定义字段注解";
}
package com.springboot.annotationRuntime;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Administrator
* @description 自定义注解
* @date 2019/12/31
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotationMethod {
String value() default "自定义方法注解";
}
package com.springboot.annotationRuntime;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Administrator
* @description 自定义注解
* @date 2019/12/31
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotationParameter {
String value() default "自定义参数注解";
}
package com.springboot.annotationRuntime;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Administrator
* @description 自定义注解
* @date 2019/12/31
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotationType {
String value() default "自定义类、接口注解";
}
package com.springboot.annotationRuntime;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
/**
* @author Administrator
* @description 自定义注解使用
* @date 2019/12/31
*/
@MyAnnotationType
public class AnnotationTest {
@MyAnnotationField
private String name="Column";
public static void main(String[] args) {
//获取类上的注解
MyAnnotationType type = AnnotationTest.class.getAnnotation(MyAnnotationType.class);
System.out.println("类注解---->"+type.value());
//根据反射获取方法
try {
Method method = AnnotationTest.class.getDeclaredMethod("test", String.class);
MyAnnotationMethod myAnnotationMethod = method.getAnnotation(MyAnnotationMethod.class);
System.out.println("方法注解---->"+myAnnotationMethod.value());
//获取方法上的所有参数注解 循环所有注解找到MyAnnotationParameter注解
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
for (Annotation[] parameterAnnotation : parameterAnnotations) {
for (Annotation annotation : parameterAnnotation) {
if (annotation instanceof MyAnnotationParameter){
System.out.println("参数上注解---->"+((MyAnnotationParameter)annotation).value());
}
}
}
method.invoke(new AnnotationTest(),"改变参数");
//获取属性上注解
MyAnnotationField myAnnotationField = AnnotationTest.class.getDeclaredField("name").getAnnotation(MyAnnotationField.class);
System.out.println("属性字段属性---->"+myAnnotationField.value());
} catch (Exception e) {
e.printStackTrace();
}
}
@MyAnnotationMethod
public static void test(@MyAnnotationParameter String name){
System.out.println("参数值---->"+name);
}
}