首页 > 编程知识 正文

自定义注解如何使用,spring注解什么时候解析

时间:2023-05-04 15:22:03 阅读:33320 作者:4045

文章引用Java :注释(Annotation )自定义注释入门

自定义注释详细信息

说在最前

文章忽视特性的基本概念

评论的本质是反射

1 .自定义注释注解其实就是一种标记,可以在程序代码中的关键节点(类、方法、变量、参数、包)上打上这些标记,然后程序在编译时或运行时可以检测到这些标记从而执行一些特殊操作

第一步:定义注释——相当于定义标记的第二步。 配置注释——,在所需的程序代码上打上标记。 分析注释——,在编译或运行时监视标记并进行特殊操作

1.2基本语法注释类型声明部分:

在注释Java中,声明语法几乎匹配,因为它类似于类、接口和枚举,但是使用的关键字不同@interface。在底层实现上,所有定义的注解都会自动继承java.lang.annotation.Annotation接口在自定义评论中,其实现部分只能定义一个:注解类型元素(annotation type element)

公共@ interfacemyannotation {公共字符串name (; int age ) ) default 18; //默认值int[] array (; } 1.2.1定义注释类型的注意事项访问修饰符必须为公共,不写的默认值为公共; 此元素的类型只能是基本数据类型、字符串、Class、枚举类型(enum )、注释类型(annotation:表示注释嵌套效果)和上述类型的1位数组。 该元素的名称一般被定义为名词。 如果注释中只有一个元素,请将名称设置为value。 (以后使用会很方便。 ); )不能在括号中定义参数,而不能在定义方法参数的位置。 这只是一种特殊语法。default表示默认值,值必须与在第二点定义的类型匹配; 如果没有默认值,这意味着在以后使用注释时必须为该类型的元素赋值。 可见,注释类型元素的语法非常奇怪,它具有属性特征(可赋值)和方法特征)。 但是这样设计是有道理的,正如在后面的章节中看到的,注释定义后是使用的时候操作元素类型像在操作属性,解析的时候操作元素类型像在操作方法

1.3元评论元注解:专门修饰注解的注解这些是专门为更好地设计定制评论的细节而设计的。

1.3.1 @Target @Target注释是为了限定特定的自定义注释适用于哪个Java要素

公共枚举元素类型{/* *类、接口(包括注释类型)或枚举的声明*/TYPE、/**属性的声明*/FIELD、/**方法的声明*/METHOD /**方法形式的参数宣言*/paramement /**生成方法的宣言*/CONSTRUCTOR,/**局部变量宣言*/LOCAL_VARIABLE, /**注释类型声明*/ANNOTATION_TYPE /**包的声明*/PACKAGE} //@CherryAnnotation只能在类、接口或方法上使用@ int age ) ) default 18; int[] array (; }1.3.2@ retention http://www.Sina.com /

评论的生命周期有三个阶段。

. java源文件阶段; 编译为class文件阶段; 运行时阶段。 同样,使用RetentionPolicy枚举类型,使用publicenumretentionpolicy {/* * * annotationsaretobediscardedbythecompiler.* (注释由编译器sompiler ) )/* * annotationsaretoberecordedintheclassfilebythecompiler * butneednotberetainedbythevmatruntime.thisisthed 这是默认行为。 () class,/* * * annotationsaretoberecordedintheclassfilebythecompileraathe

by the VM at run time, so they may be read reflectively. * (注解将被编译器记录在class文件中,而且在运行时会被虚拟机保留,因此它们能通过反射被读取到) * @see java.lang.reflect.AnnotatedElement */ RUNTIME} 如果一个注解被定义为RetentionPolicy.SOURCE,则它将被限定在Java源文件中,那么这个注解即不会参与编译也不会在运行期起任何作用,这个注解就和一个注释是一样的效果,只能被阅读Java文件的人看到;如果一个注解被定义为RetentionPolicy.CLASS,则它将被编译到Class文件中,那么编译器可以在编译时根据注解做一些处理动作,但是运行时JVM(Java虚拟机)会忽略它(例如@Override),我们在运行期也不能读取到;如果一个注解被定义为RetentionPolicy.RUNTIME,那么这个注解可以在运行期的加载阶段被加载到Class对象中。那么在程序运行阶段,我们可以通过反射得到这个注解,并通过判断是否有这个注解或这个注解中属性的值,从而执行不同的程序代码段。我们实际开发中的自定义注解几乎都是使用的RetentionPolicy.RUNTIME;在默认的情况下,自定义注解是使用的RetentionPolicy.CLASS。 1.3.3 @Documented

@Documented注解,是被用来指定自定义注解是否能随着被定义的java文件生成到JavaDoc文档当中。

1.3.4 @Inherited

@Inherited注解,是指定某个自定义注解如果写在了父类的声明部分,那么子类的声明部分也能自动拥有该注解。@Inherited注解只对那些@Target被定义为ElementType.TYPE的自定义注解起作用。

2. 自定义注解的使用

回顾一下注解的使用流程:

第一步,定义注解——相当于定义标记;第二步,配置注解——把标记打在需要用到的程序代码中;第三步,解析注解——在编译期或运行时检测到标记,并进行特殊操作。

到目前为止我们只是完成了第一步,接下来我们就来学习第二步,配置注解,如何在另一个类当中配置它。

2.1 在具体额Java类上使用注解

首先,定义一个注解、和一个供注解修饰的简单Java类

@Retention(RetentionPolicy.RUNTIME)@Target(value = {ElementType.METHOD})@Documentedpublic @interface MyAnnotation { String name(); int age() default 18; int[] score();} public class Student{ public void study(int times){ for(int i = 0; i < times; i++){ System.out.println("Good Good Study, Day Day Up!"); } }} 2.2 特殊语法

特殊语法一:如果注解本身没有注解类型元素,那么在使用注解的时候可以省略(),直接写为:@注解名,它和标准语法@注解名()等效!

@Retention(RetentionPolicy.RUNTIME)@Target(value = {ElementType.TYPE})@Documentedpublic @interface FirstAnnotation {} //等效于@FirstAnnotation()@FirstAnnotationpublic class JavaBean{//省略实现部分}

特殊语法二:如果注解本本身只有一个注解类型元素,而且命名为value,那么在使用注解的时候可以直接使用:@注解名(注解值),其等效于:@注解名(value = 注解值)

@Retention(RetentionPolicy.RUNTIME)@Target(value = {ElementType.TYPE})@Documentedpublic @interface SecondAnnotation {String value();} //等效于@ SecondAnnotation(value = "this is second annotation")@SecondAnnotation("this is annotation")public class JavaBean{//省略实现部分}

特殊用法三:如果注解中的某个注解类型元素是一个数组类型,在使用时又出现只需要填入一个值的情况,那么在使用注解时可以直接写为:@注解名(类型名 = 类型值),它和标准写法:@注解名(类型名 = {类型值})等效!

@Retention(RetentionPolicy.RUNTIME)@Target(value = {ElementType.TYPE})@Documentedpublic @interface ThirdAnnotation {String[] name();} //等效于@ ThirdAnnotation(name = {"this is third annotation"})@ ThirdAnnotation(name = "this is third annotation")public class JavaBean{//省略实现部分} 3.自定义注解的运行时解析

系统是如何在程序运行时检测到注解,并进行一系列特殊操作

只有当注解的保持力处于运行阶段,即使用@Retention(RetentionPolicy.RUNTIME)修饰注解时,才能在JVM运行时,检测到注解,并进行一系列特殊操作。

3.1 反射操作获取注解

因此,明确我们的目标:在运行期探究和使用编译期的内容(编译期配置的注解),要用到Java中的灵魂技术——反射!

public class TestAnnotation { public static void main(String[] args) { try{ //获取Student的Class对象 Class stuClass = Class.forName("com.hong.example.Student"); //这里的形参不能写成Integer.class,应该写int.class Method stuMethod = stuClass.getMethod("study",int.class); if (stuMethod.isAnnotationPresent(MyAnnotation.class)){ System.out.println("Student类上配置了MyAnnotation注解!"); //获取该元素上指定类型的注解 MyAnnotation myAnnotation = stuMethod.getAnnotation(MyAnnotation.class); System.out.print("name: "+myAnnotation.name()+", age: "+myAnnotation.age()+", score:"); for (int i = 0 ;i < myAnnotation.score().length;i++){ System.out.print(myAnnotation.score()[i]+" "); } }else{ System.out.println("Student类上没有配置MyAnnotation注解"); } System.out.println(); }catch (ClassNotFoundException | NoSuchMethodException e){ e.printStackTrace(); } }} 如果我们要获得的注解是配置在方法上的,那么我们要从Method对象上获取;如果是配置在属性上,就需要从该属性对应的Field对象上去获取,如果是配置在类型上,需要从Class对象上去获取。总之在谁身上,就从谁身上去获取!isAnnotationPresent(Class<? extends Annotation> annotationClass)方法是专门判断该元素上是否配置有某个指定的注解;getAnnotation(Class<A> annotationClass)方法是获取该元素上指定的注解。之后再调用该注解的注解类型元素方法就可以获得配置时的值数据;反射对象上还有一个方法getAnnotations(),该方法可以获得该对象身上配置的所有的注解。它会返回给我们一个注解数组,需要注意的是该数组的类型是Annotation类型,这个Annotation是一个来自于java.lang.annotation包的接口。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。