当前位置: 首页 > 科技观察

关于Java注解(annotation)编程

时间:2023-03-13 02:04:43 科技观察

前言今天在看自己之前写的代码,发现自己对注解的理解不是很透彻。我经常选择性地忽略对注解实现的探索,于是自己查找资料研究。注解的实现格式是什么从代码来看,我们知道注解的实现格式是:public@interfaceMyAnnotation{propertylist;}所以我们第一直觉注解可能是一个接口。通过查询资料(可以使用反编译软件),其实@interface是自定义接口对注解接口的继承,@interface其实是一个语法糖。importjava.lang.annotation.注解;publicinterfaceMyAnnotationextendsAnnotation{propertylist;}使用位置类、方法、成员变量、形参位置。从不同的分类角度,我们可以对注解进行不同的分类,但是在了解了注解的实现原理之后,我们就会明白,用法和实现方法其实是一回事。来源1.JDK注解:一般用作编译时的注解,比如我们最熟悉的@Override。2.第三方框架注解3.自定义注解运行机制(保留策略)@Retention({retentionpolicy})public@interfaceMyAnnotation{propertylist;}1.源码(SOURCE)注解:注解只存在于源码,编译后into.class文件已经不存在了,也就是说,它只能起到“看”的作用。2、编译(CLASS)注解:源代码和.class文件中都存在注解(JDK自带的注解都是编译时注解),一般用于语法校验。3、运行时(RUNTIME)注解:在运行阶段仍然起作用,甚至会影响运行逻辑的注解(@Autowired属于运行时注解)。第三方框架和自定义注解一般采用运行时保留策略,可以实现依赖注入、切面编程等功能。元注解其实在上面,我们已经看到了一个元注解(@Retention)。元注释是添加到描述注释的注释的注释。一共有5个。1、@Documented会在生成javadoc时显示@Documented注解。2、@Target(key)定义了action、Method、Class等的位置。9.@Inherited被@Inherited注解的注解修改为父类。如果它的子类没有被其他注解修饰,它的子类也继承父类的注解。10.@Retention(key)上面的retentionpolicy注解影响注解的效果。6、@Repeatable(不重要)@Repeatable注解是元注解,用于声明其他类型的注解,以表明声明的注解是可重复的。@Repeatable的值是另一个注解,它可以通过另一个注解的值包含这个可重复的注解。如何使用我们先了解一下注解的粗浅使用。最简单的,使用自定义注解分为三个步骤:定义注解、使用注解和读取注解。摘自:https://www.zhihu.com/question/47449512/answer/658228092只要牢牢掌握这三个步骤,我们就可以掌握注解的使用。定义注解是因为注解的基本作用是根据注解中的值来决定被注解的代码块如何执行。因此,在定义注解时,除了根据功能添加注解外,还需要根据业务意义编写合适的方法名。比如我们要写锁注解:@Documented@Retention(RUNTIME)@Target({TYPE,METHOD})public@interfaceLock{//输入锁名StringlockName();//锁值Stringkey();//锁级别intlevel();//ExceptionStringexception()default"";}在一个注解中,可以返回的类型有:基本数据类型、String、enum、Class、其他注解、一维数组前者。注意:如果没有默认值,使用时必须输入参数。使用注解在注解的地方进行注解,输入参数中必须输入的参数。Tips:如果注解中只有一个函数,虽然在使用时可以不加函数名直接作为参数输入,但我个人建议自定义注解,在输入参数时写上完整的函数名,以增强代码的可读性。让我们先考虑阅读注释。如果我们自己实现一个读取注解的方法,应该怎么实现呢?目前想到的无外乎两种:1.在字符串或者字节码文件中查找注解:这个判断不好写,复杂的字符串也处理不了。2、通过反射获取类、方法、成员变量的注解。明眼人都能看出2比1靠谱,而且也容易实现。最简单的阅读方式:publicstaticvoidmain(String[]args)throwsNoSuchMethodException{ClassmodelClazz=Module.class;Methodmethod=modelClazz.getMethod("lock",null);LockannotationLock=method.getAnnotation(Lock.class);//获取valueStringlockName=annotationLock.lockName();}这也是框架注解的基本实现原理,因为要获取注解的具体代码块,一般需要扫包。对于切面编程,在引入了对aspectj的依赖之后,我们有了更简单的调用方式:getAnnotation(Lock.class);lock.lockName();}切面编程和joinpoint的具体知识可以参考:https://blog.csdn.net/qq_15037231/article/details/80624064我们可以总结一下作用annotations到目前为止注释的作用。*Programminghints保留策略是源代码注解,一般是提示性的注解,比如@deprecated。*用于切面,减少运行注解的重复代码保留策略,零侵入改变函数的运行效果,一般用于重复性功能,如日志输出,数据格式校验等*简化配置信息,项目结构主要针对springboot框架。因为注解可以取值,所以在设置默认配置信息的同时也支持输入配置信息。*格式检查一般是对代码的语法检查,存在于jdk的注解包中,比如@Override。