JavaApe的命脉!自从JavaEE框架进入SpringBoot时代,注解就是Java程序员的命脉,面向注解的编程已经成为日常操作!换句话说就是:如果没有注解,我们什么也做不了哇(滑稽)。这不是很危险吗!所以本文就讲一下注解的相关操作,自己写个注解感受下原理。掌握了根本的东西,心里自然不会慌乱。注解的基本原理首先得说,注解不是高深的东西,不用怕!顾名思义,它的本意是用来做标记的:可以在类、字段变量、方法、接口等地方做一个特殊的标记,为后续做一些工作,比如:代码生成、数据校验、资源整合等做铺垫。没错,就是为了标记!一旦在代码上标注了注解,我们就可以结合Java强大的反射机制,在运行时动态获取注解信息,从而执行很多其他的逻辑,完成我们想要的自动化工作。所以,反思一定要学好!来!手工创建注解在我之前的文章《听说你还在手写复杂的参数校验?》中提到过,Spring本身提供了很多有用的注解,可以用来帮助我们方便的做数据校验的工作。比如在不支持注解的情况下,我们要验证Student类:publicclassStudent{privateLongid;//学号privateStringname;//姓名privateStringmobile;//手机号(11位)}如果是,我们只能手写验证判断测试:@PostMapping("/add")publicStringaddStudent(@RequestBodyStudentstudent){if(student==null)return"传入的Student对象为null,请传值";if(student.getName()==null||".equals(student.getName()))return"传入学生姓名为空,请传值";if(student.getScore()==null)return"传入学生成绩为空,请传值Thevalue";if((student.getScore()<0)||(student.getScore()>100))return"传入的学生分数错误,分数应该在0~100之间";if(student.getMobile()==null||"".equals(student.getMobile()))return"传入的学生电话为空,请传值";if(student.getMobile().length()!=11)return"传入学生ph的长度一个数字错了,应该是11位数字”;studentService.addStudent(student);//将student对象存入MySQL数据库return"SUCCESS";}这个很麻烦!但是借助Spring提供的注解,数据的校验工作可以变得非常优雅,像这样:name为空串,请传值")privateStringname;//姓名@NotNull(message="传入分数为空,请传值")@Min(value=0,message="传入学生分数有误,分数应在0~100之间")@Max(value=100,message="来电学生分数有误,分数应在0到100之间")privateIntegerscore;//Score@NotNull(message="来电为null,请传值")@NotEmpty(message="来电号码为空串,请传值")@Length(min=11,max=11,message="来电号码长度错误,必须为11位")privateStringmobile;//电话号码}所以很多人表示疑惑,这些注解是如何实现功能的?今天本文以上面的@Length注解为例,自己实现一下。学了这个之后,其他注解的实现原理都差不多,一共三步。第一步:首先定义注解:@Length@Target({ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)public@interfaceLength{intmin();//允许的字符串长度的最小值intmax();//AllowedThemaximumvalueofthestringlengthStringerrorMsg();//Customizederrormessage}这里有几点解释:1.注解的定义有点像定义接口,唯一不同的是需要一个@符号添加在它的前面。2.注解成员变量只能使用基本类型,String或者enum枚举,比如int,不能使用Integer的封装类型。Note3.对于像上面的@Target和@Retention那样添加到注解定义中的注解,我们称之为“元注解”。Meta-annotation是一种专门用于给注释添加注释的注释。哈哈,真是一口。简单理解,元注解是固有的注解,可以直接在注解的定义中使用。4、@Target(xxx)用于说明自定义注解可以用在什么地方,例如:ElementType.FIELD:表示自定义注解可以用于类变量ElementType.METHOD:表示自定义注解可以用于classmethodsElementType.TYPE:说明自定义注解可以用于类本身,接口或者枚举类型等等。。还有很多,如果记不住,建议现在查一下5、@Retention(xxx)用于说明你自定义的注解的生命周期,如:@Retention(RetentionPolicy.RUNTIME):表示注解可以保留到运行时,所以可以通过反射获取注解信息@Retention(RetentionPolicy.CLASS):表示注解被编译器编译成类文件,但是运行时会忽略@Retention(RetentionPolicy.SOURCE):表示该注解只在源文件中有效,在编译时会被忽略。所以声明周期从长到短是:RUNTIME>CLASS>SOURCE。一般来说,如果需要在运行时动态获取注解信息,还是要用到RUNTIME,如本文所用。第二步:获取注解并验证如果想在运行时获取注解包含的信息怎么办?当然,你得用到Java的反射相关知识!下面写了一个验证函数validate()。代码会逐行使用注释来说明你想要达到的目的。仔细看每一行的注释:publicstaticStringvalidate(Objectobject)throwsIllegalAccessException{//首先通过反射获取object对象的类。哪些字段//本文可以获取到Student类的三个字段:id,name,mobileField[]fields=object.getClass().getDeclaredFields();//for循环逐字段查看whichfieldAnnotationissuperscriptedfor(Fieldfield:fields){//if判断:检查字段上是否标注@Length注解if(field.isAnnotationPresent(Length.class)){//通过反射获取字段上的注解@Length注解详解Lengthlength=field.getAnnotation(Length.class);field.setAccessible(true);//让我们在反射时访问私有变量//使用反射获取字段的实际值intvalue=((String)field.get(object)).length();//比较字段的实际值和注解上标注的值if(value
