JavaAnnotations和JavaComments。英文的差别很大,中文的差别就比较费解了。随着Java语言的诞生,JavaComments应运而生。它们含义明确,易于理解。它们是源代码中的解释信息,通常用于帮助代码编写者理解代码。JavaAnnotations出现较晚,在Java1.5(Java5)中引入。目前(2022年)Java部署的主流是Java8(Java1.8),最新发布的是Java11(Java1.11)。但是JavaAnnotations注解的含义和作用有些让人迷惑,比如官方文档中:注解不直接影响程序语义,但确实会影响工具和库对待程序的方式,进而影响程序的语义正在运行的程序。注释可以从源文件、类文件中读取,也可以在运行时反射读取。Annotations注释不直接影响程序的语义,但它们确实影响工具和库处理程序的方式,进而影响正在运行的程序的语义。Annotations注释可以在运行时从源文件、类文件或反射中读取。随着“toolsandlibraryhandlers”的流行,比如Spring全家桶在Java开发中越来越流行,@RequestXXX这样的表达式随处可见,后生成的JavaAnnotations也逐渐进入开发商的视野。但是要用几句话来解释什么是JavaAnnotations注释以及它们是如何起作用或工作的并不容易。我们主导的Java中的Java开发框架GWA2(https://ufqi.com/dev/gwa2/)并没有过多的依赖JavaAnnotations注解,主要是我们考察了Reflection等相关技术的使用时,是发现其性能会下降,安全性会受到影响。由于1)java.lang.reflection的性能和安全问题,我们目前不使用它作为路由或动态模块调用。鉴于Reflection相关技术的性能和安全相关问题,目前Java中的GWA2并未将其视为路由和动态模块加载的技术手段。然而,Java开发行业似乎已经形成了一堆站在“巨人的肩膀上”的积木。如果第一颗纽扣歪了,大家就顺顺利利地继续歪下去。所谓的性能和安全问题是可以克服的,解决不了的部分也在可接受范围内,大家开心就好。最近接手了两个Java开发的二期项目。基于JavaSpring全家桶,虽然项目技术栈是Java,但是其依赖的各种第三方组件已经达到了让人眼花缭乱的程度(如下图)。JavaSpringcomponentsuite既然JavaAnnotations这么重要,自然要搞清楚。然而,当我们试图向一些工程师解释什么是JavaAnnotations以及如何解释时,却并不容易搞清楚。一方面是Java语言本身的复杂性,另一方面是Annotations是上层应用,可选的。经过一番寻找、思考和探索,我认为以下两个例子可以清楚地说明JavaAnnotations注解的基本原理和应用实践,回答JavaAnnotations注解是什么、为什么以及如何使用的问题。示例1.使用JavaAnnotations标记对象类、实例、方法和属性有或没有属性。本例来自官网(https://docs.oracle.com/javas...)e.g.1.1。SampleTestTag.java:自定义一个JavaAnnotation注解对象,其中@Retention和@Target是注解的注解,称为“Meta-annotation”,注解类的名称是什么?在名称前的符号处添加“@”importjava.lang.annotation.*;@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public@interfaceSampleTestTag{}e.g.1.2.FooBar.java:创建一个对象类FooBar,使用在SampleTestTag上面创建的Java注解staticvoidm4(){}@SampleTestTagpublicstaticvoidm5(){}publicstaticvoidm6(){}@SampleTestTagpublicstaticvoidm7(){thrownewRuntimeException("Crash");}publicstaticvoidm8(){}}例如1.3。FooBarTest.java:创建测试程序,调用对象类FooBar,测试SampleTestTag的区分功能importjava.lang.reflect.*;publicclassFooBarTest{publicstaticvoidmain(String[]args)throwsException{intpassed=0,失败=0;对于(方法米:Class.forName(args[0]).getMethods()){if(m.isAnnotationPresent(SampleTestTag.class)){try{m.invoke(null);通过++;}catch(Throwableex){System.out.printf("测试%s失败:%s%n",m,ex.getCause());失败++;}}}System.out.printf("Passed:%d,Failed%d%n",passed,failed);}}测试程序的预期结果大致是:$javaFooBarTestFooBarTestpublicstaticvoidFoo.m3()failed:java.lang.RuntimeException:BoomTestpublicstaticvoidFoo.m7()failed:java.lang.RuntimeException:CrashPassed:2,Failed2这个例子的意思是通过自定义一个注解,对象类的一些方法可以被标记。核心方法是isAnnotationPresent。这只是一个简单的例子。如果这种方式可行,就有这种简单的方法或范式可以对对象类、实例、方法和属性进行分类,就好像打开了潘多拉魔盒,赋予了开发者无尽的分类能力。当这个能力可用时,根据运行时的分类,让A类运行,让B类关闭;在英国地区办A类,在北美办B类;让VIP跑A级,让非VIP让孩子看A级,让老人看B级,其他人看C级……显然这个能力很强大,但同时也暴露了它的复杂性.开发人员看到的代码和最终运行时的代码可能会高度不一致。虽然代码放在哪里,具体运行那些代码取决于运行时的状态。结果是所见即所得的可怕现象。例2.使用JavaAnnotations注解来标记某个对象的类、实例、方法和属性具有某个属性的某个赋值。这就是实例1的进化升级,如果实例1提供了一个简单的二元分类,某个对象有没有,是和否,那么实例2会无限升级这个能力,让一个对象拥有某个属性,并且这个属性的赋值是可以千变万化的。更多全文内容:两个例子清晰解释JavaAnnotations注解|-UFQI-Blog,https://ufqi.com/blog/gwa2-ja...
