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

Java注解在框架开发中的妙用

时间:2023-03-13 01:37:10 科技观察

如果你不会使用注解,你肯定不好意思跟别人说你学过Spring和Mybatis,因为他们大量使用注解。可见注解在开发领域已经得到了广泛的应用。注解的好处:1、能够看懂别人写的代码,尤其是框架相关的代码。2、可以用一个或多个注解来代替可能需要很多配置文件和很多逻辑才能实现的内容,使编程更简洁,代码更清晰。3.(强调)钦佩。(但是你怎么打动别人呢?知道怎么用注解不是目的,用自定义注解解决问题才是最重要的。)比如:如果你在面试的时候跟老板说你可以用注解,那老板觉得你还好;但是如果老板发现你可以自定义注解来解决问题,老板肯定会眼前一亮。注解的概念是在java1.5版本中提出来的,说是Java为原程序中的元素提供了一种关联任何信息和任何元数据的方式。一、Java中常见的注解1)JDK注解JDK注解分为三类:案例:我们先新建一个接口people,如下:publicinterfacepeople{publicStringname();publicintage();publicvoidwork();}然后新建一个classChild实现类people的接口,实现这个类的方法:publicclassChildimplementspeople{@OverridepublicStringname(){returnull;}@Overridepublicintage(){return0;}@Overridepublicvoidwork(){}看到这里,我们发现所有的方法这里会加一个@Override标签,它告诉我们,也告诉编译器,我们的方法必须覆盖类people中的方法。比如我在类people中注释掉某个方法://publicStringname();再看类Child中的name方法,会报错。这样,以后看到@Override,就可以认为这个方法重写了一个接口的某个方法。那么,我们回过头来看,班级人里面是有工作方法的。在这里我们可以理解人是要工作的,但并不是所有的人都在工作,那么我们应该怎么办呢?如果正在使用这个接口,我们不能删除这个方法。这时候,我们可以这样做:@Deprecatedpublicvoidwork();@Deprecated标记表示此方法已过时。在实践中,它有什么样的应用场景?我们正在构建一个测试类:publicclassTest{publicvoidwork(){peoplepeople=newChild();!people.work();}}这时候我们会发现myeclipse会给出警告,work中间会出现一个破折号,说明这个方法已经过时了。那么问题来了,这个方法虽然过时了,但是我们这么嚣张,非要用,怎么办呢?只需这样做:publicclassTest{@SuppressWarnings("deprecation")publicvoidwork(){people=newChild();people.work();}}所以我们忽略警告。@SuppressWarnings("deprecation")表示我们忽略诸如弃用之类的警告。2)Java第三方注解二、注解的分类1)按运行机制划分:【源码注解→编译时注解→运行时注解】源码注解:只存在于源代码中,编译成.class文件不存在。编译时注释:存在于源代码和.class文件中。像前面的@Override、@Deprecated、@SuppressWarnings,都是编译期注解。Runtimeannotations:在运行阶段仍然起作用,甚至影响运行逻辑的注解。像@Autowired自动注入的注解是运行时注解,会在程序运行的时候自动注入你的成员变量。2)按来源划分:[AnnotationsfromJDK——Annotationsfromthethirdparty——Customannotations]3)Meta-annotations:元注解是注解的注解,可以理解为注解的注解是元注解。3.自定义注解我们分四步分析自定义注解:自定义注解的语法要求:@Target({ElementType.METHOD,ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Inherited@Documentedpublic@interfaceDescription{Stringdesc();Stringauthor();intage()default18;}首先要明确一点,这不是接口,是使用@interface关键字定义的注解。然后我们看下面的方法,Stringdesc();虽然很像接口中的方法,但实际上只是注解中的一个成员变量(成员声明时不带参数,无异常),intage()default18;(成员变量可以使用default指定一个默认值)。最后,我们需要知道:①.成员类型有限制,合法类型包括基本数据类型和String、Class、Annotation、Enumeration等②。如果注解只有一个成员,则成员名必须命名为value(),使用时可以忽略成员名和赋值号(=)。③.注解类可以没有成员,没有成员的注解称为标识注解。元注解:你有没有注意到上面的代码有一处没有提到?没错,就是我们所说的元注解:@Target({ElementType.METHOD,ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Inherited@Documented先来看第一行:@Target是函数这个注解Domain,ElementType.METHOD是这个注解作用域的列表,METHOD是方法声明,另外还有:CONSTRUCTOR(构造方法声明),FIELD(字段声明),LOCALVARIABLE(局部变量声明),METHOD(方法声明),PACKAGE(包声明),PARAMETER(参数声明),TYPE(类接口)第二行:@Retention是它的生命周期。不是说注解是按照运行机制分类的吗?RUNTIME在运行时是存在的,可以通过反射读取。此外还有:SOURCE(只在源码中显示,编译时丢弃)、CLASS(编译时记录在类中,运行时忽略)、RUNTIME(运行时存在,可以通过反射读取)第三种行:@Inherited是一个标识元注解,允许子注解继承它。第四行:@Documented,生成javadoc时会包含注解。使用自定义注解:使用注解语法:@(=,=,...)case:@Description(desc="iamColor",author="boy",age=18)publicStringColor(){return"red";}这里的Description就是我们刚刚在自定义注解语法要求中定义的注解,然后我们可以给它的每一个成员变量赋值,注意数据类型。值得注意的是,因为我们前面定义的作用域是在方法和类接口上,所以这个注解用在Color()方法上是没有问题的。解析注解的概念:通过反射获取类、函数或成员的运行时注解信息,从而实现动态控制程序运行的逻辑。准备工作:接下来,我们开始测试:publicclassParseAnn{publicstaticvoidmain(String[]args){try{//使用类加载器加载类Classc=Class.forName("com.test.Child");//找到注解abovetheclassbooleanisExist=c.isAnnotationPresent(Description.class);//上面的方法是利用这个类判断是否有Description之类的注解if(isExist){//获取注解实例并解析该类上述注释的结果Descriptiond=(Description)c.getAnnotation(Description.class);System.out.println(d.value());}}catch(ClassNotFoundExceptione){e.printStackTrace();}}}输出:从iamclassannotation可以看出,我们成功解析了Child类上的注解。接下来我们继续解析方法上的注解://获取所有方法Method[]ms=c.getMethods();//遍历所有方法for(Methodm:ms){booleanisExist1=m.isAnnotationPresent(Description.class);if(isExist1){Descriptiond1=m.getAnnotation(Description.class);System.out.println(d1.value());}}输出结果:iamclassannotationiammethodannotation可以看到,我们成功解析了上面注解的方法。//另一种分析方法for(Methodm:ms){//获取方法上的所有注解Annotation[]as=m.getAnnotations();for(Annotationa:as){//使用二元运算符判断a是否为anInstanceofDescriptionif(ainstanceofDescription){Descriptiond=(Description)a;System.out.println(d.value());}}}也可以得到上面的效果。此时,如果在Description类中更改元注解,如:@Retention(RetentionPolicy.RUNTIME)→@Retention(RetentionPolicy.SOURCE),然后运行程序,会出现什么结果呢?如果改成CLASS呢?你想试一试吗?