Java自定义注解Annotation

news/2024/5/19 2:44:02 标签: java, 反射, annotations

Java自定义注解Annotation

  • 一、注解(Annotation)概述
  • 二、元注解
    • @Documented
    • @Target
    • @Retention
    • @Inherited
  • 三、定义Annotation
    • 使用注解
    • 处理注解
    • 注意事项
    • 常用注解方法

一、注解(Annotation)概述

注解是放在Java源码的类、方法、字段、参数前的一种特殊“注释”。

注释会被编译器直接忽略,注解则可以被编译器打包进入class文件,因此,注解是一种用作标注的“元数据”。

Java从JDK5.0开始便提供了四个meta-annotation用于自定义注解的时候使用,这四个注解为:@Target,@Retention,@Documented 和@Inherited。

二、元注解

元注解是给注解进行注解,或者说注解可以修饰其他注解,可以理解为注解的注解就是元注解。

@Documented

是一个标记注解,木有成员,用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。

java">@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}

@Target

最常用的元注解是@Target。@Target用于描述注解的使用范围(即:被描述的注解能够被应用于源码的哪些位置):

java">@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    /**
     * Returns an array of the kinds of elements an annotation type
     * can be applied to.
     * @return an array of the kinds of elements an annotation type
     * can be applied to
     */
    ElementType[] value();
}
@Target 注解只有唯一成员value,类型为ElementType数组。ElementType可取的值有:
java">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
}
java">TYPE:用于描述类、接口(包括注解类型)enum声明
FIELD:用于描述成员变量
METHOD:用于描述方法
PARAMETER:用于描述参数
CONSTRUCTOR:用于描述构造器
LOCAL_VARIABLE:用于描述局部变量
 ANNOTATION_TYPE:注释类型声明
 PACKAGE:用于描述包

@Retention

指定被描述的注解在什么范围内有效,即定义了Annotation的生命周期。

如果@Retention不存在,则该Annotation默认为CLASS。因为通常我们自定义的Annotation都是RUNTIME

java">@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}

RetentionPolicy可取的值

java">public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     */
    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,

    /**
     * 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:在源文件中有效(即源文件保留);

CLASS:在class文件中有效(即class保留);

RUNTIME:在运行时有效(即运行时保留)。

@Inherited

使用@Inherited定义子类是否可继承父类定义的Annotation。@Inherited仅针对@Target(ElementType.TYPE)类型的annotation有效,并且仅针对class的继承,对interface的继承无效

某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。类A被@Inherited标注 , 类B继承类A , 则类B默认也定义了该注解

java">@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}

三、定义Annotation

用@interface定义注解

java">public @interface CustomAnnotation {
   
}

定义参数、默认值 ,核心参数使用value名称

java">public @interface CustomAnnotation {
 	String name() default "";
    String description() default "";
}

用元注解配置注解

必须设置@Target来指定Annotation可以应用的范围

应当设置@Retention(RetentionPolicy.RUNTIME)便于运行期读取该Annotation
java">@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomAnnotation {
    String name() default "";
    String description() default "";
}

使用注解

java">@CustomAnnotation(name = "Student",description="这是Student类")
public class Student implements Serializable{

	@CustomAnnotation(name = "name",description="这是name属性")
	private String name;

	@CustomAnnotation(name = "getName",description = "获取name属性")
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

处理注解

java">    public static void main(String[] args) {
        Class<Student> aClass = Student.class;
        //是否被@CustomAnnotation标注
        if (aClass.isAnnotationPresent(CustomAnnotation.class)) {
            //获取@CustomAnnotation注解对象
            CustomAnnotation annotation = aClass.getAnnotation(CustomAnnotation.class);

            // 获取@CustomAnnotation注解所对应的方法与值
            try {
                Method method1 = CustomAnnotation.class.getMethod("name");
                String name = (String) method1.invoke(annotation);
                System.out.println(name);

                Method method2 = CustomAnnotation.class.getMethod("description");
                String description = (String) method2.invoke(annotation);
                System.out.println(description);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            if (method.isAnnotationPresent(CustomAnnotation.class)) {
                CustomAnnotation annotation = method.getAnnotation(CustomAnnotation.class);
                System.out.println(annotation.name());
                System.out.println(annotation.description());
            }
        }

        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            if (declaredField.isAnnotationPresent(CustomAnnotation.class)) {
                CustomAnnotation annotation = declaredField.getAnnotation(CustomAnnotation.class);
				System.out.println(annotation.name());
				System.out.println(annotation.description());

                String type = null;
                // 判断类型
                if (int.class.isAssignableFrom(declaredField.getType()) || Integer.class.isAssignableFrom(declaredField.getType())) {
                    type = "Integer";
                } else if (String.class.isAssignableFrom(declaredField.getType())) {
                    type = "String";
                }
                System.out.println(type);
            }
        }
    }

注意事项

Annotation的成员定义必须满足以下三点:

成员只能用public或默认(default)这两个访问权修饰;

成员的类型只能是基本类型,String,Enum,Class,Annotation以及它们的数组类型;

如果只有一个成员,最好将其名称设为value。

常用注解方法

java"><T extends Annotation> T getAnnotation(Class<T> annotationType) // 根据annotationType获取注解对象

Annotation[] getAnnotations() // 获取所有注解

boolean isAnnotationPresent(Class<T> annotationType) // 判断当前元素是否被annotationType注解

Annotation[] getDeclareAnnotations() // 与getAnnotations() 类似,但是不包括父类中被Inherited修饰的注解

http://www.niftyadmin.cn/n/876541.html

相关文章

性能测试之Jmeter的入门使用

性能测试之Jmeter的入门使用Jmeter概述安装JmeterJmeter的基本使用添加线程组添加Http请求添加察看结果树添加聚合报告添加断言添加断言结果执行测试自定义变量CSV可变参数数据库压力测试添加数据库驱动程序添加JDBC取样器添加JDBC配置执行测试结果分析总结JMeter Address Alre…

JWT的详细使用

JWT的详细使用一、JWTJWT概述优缺点令牌结构头部&#xff08;Header&#xff09;载荷&#xff08;playload&#xff09;签证&#xff08;signature&#xff09;Base64URL算法二、JJWT签发与验证token引入依赖创建token解析token设置过期时间自定义claims三、拦截器校验Token创建…

消息中间件之ActiveMQ的入门使用

消息中间件之ActiveMQ的入门使用一、JMS入门消息中间件常见消息中间件JMS简介JMS消息传递类型二、ActiveMQ下载与安装三、ActiveMQ入门1.引入依赖2.点对点模式消息生产者消息消费者执行测试3.发布/订阅模式消息生产者消息消费者执行测试四、Spring整合ActiveMQ1.spring-mq.xml配…

Spring Cloud之Eureka服务治理

Spring Cloud之Eureka服务治理一、Eureka概述服务端与客户端的关系注册中心的作用二、Eureka Server搭建单机环境搭建高可用环境搭建三、Eureka服务注册引入依赖配置application.yml启动类添加注解提供服务启动参数配置执行测试四、服务消费引入依赖配置启动类执行测试五、Eure…

注解 自用解析

* 注解&#xff1a;说明程序的 由计算机辨别 * 注释&#xff1a;代码说明* 定义&#xff1a;注解&#xff08;Annotation&#xff09;&#xff0c;也叫元数据。一种代码级别的说明。是一个特性&#xff0c;与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局…

Spring Cloud之Ribbon客户端负载均衡

Spring Cloud之Ribbon客户端负载均衡一、RibbonRibbon概述二、RestTemplateGet请求POST请求PUT请求DELETE请求三、创建Eureka-Server引入依赖配置配置启动类四、创建服务提供方引入依赖配置配置启动类暴露服务接口五、创建Ribbon消费者引入依赖配置Ribbon参数配置启动类消费服务…

反射 自用解析

(含从配置文件加载类) * 框架&#xff1a;半成品软件。可以在框架的基础上进行软件开发&#xff0c;简化编码&#xff0c;基础原理用到反射 * 反射&#xff1a;将类的各个组成部分封装为其他对象&#xff0c;这就是反射机制* 好处&#xff1a;1. 可以在程序运行过程中&#xf…

Redis之缓存穿透、击穿、雪崩问题与缓存删除、淘汰策略

Redis之缓存穿透、击穿、雪崩问题与缓存删除、淘汰策略一、缓存问题与解决缓存穿透缓存击穿缓存雪崩三者区别缓存预热二、缓存淘汰机制删除策略内存淘汰机制一、缓存问题与解决 缓存穿透 缓存穿透是指查询缓存和DB中都不存在的数据。 通过id查询&#xff0c;id一般大于0&…