在开发过程中,我们经常使用各种各样的注解,诸如@Controller、@Service、@Mapper等,是不是有好多码农像我一样机械的复制或者敲几个注解,知道加几个注解有什么样的效果却没有具体的去了解注解?就像我们每天跟隔壁邻居打招呼却不知道他们怎么称呼,是做什么工作的。
一、认识注解
关于注解,我个人理解注解就相当于一个标签,贴在商品上顾客就知道这个商品卖多少钱,打不打折。我们把一个注解放在一个方法上,我们就可以看出这个方法是不是重写、覆盖的接口的方法,这个方法是不是废弃、过时的方法。
/*@Override注解表示该方法是实现的接口的方法*/
@Override
public Motto getMottoById(Integer id) {
return this.mottoMapper.getMottoById(id);
}
二、自定义注解
我们通过自定义一个注解来了解下注解的工作原理,在开始编码之前,我们先介绍两个java自带的元注解(在自定义注解时使用到的注解称为元注解)。
@Retention
@Retention定义了该注解被保留的时间长短:某些注解仅出现在源代码中,而被编译器丢弃;而另一些却被编译在class文件中;编译在class文件中的注解可能会被虚拟机忽略,而另一些在class被装载时将被读取(请注意并不影响class的执行,因为Annotation与class在使用上是被分离的)。我们看@Retention的源码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
只有一个枚举类型的value属性,我们看RetentionPolicy的源码:
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
RetentionPolicy可取三个值:RESOURCE、CLASS、RUNTIME,分别表示该自定义注解是存活到源码阶段还是存活到编译成的class文件中,还是存活到运行阶段。
@Target
@Target说明了注解所修饰的对象范围,:注解可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在注解类型的声明中使用了target可更加明晰其修饰的目标。
@Target的源码和@Retention的类似,我就偷下懒不复制出来了,也是一个value属性表示注解所修饰的对象的范围。
总之@Retention从时间上定义了该注解能活多久,@Target从空间上定义了该注解能在那些地方活动。
好了,下面我们来演示一个自定义注解
首先,我们新建一个注解类MyAnnotation
package com.example.demo.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by yuxl on 2019/1/16.
* @Retention(RetentionPolicy.RUNTIME)表示该注解可以活到运行期
* @Target({ElementType.TYPE,ElementType.METHOD})表示该注解可以放在类上、方法上
* 我们给该自定义注解定义了两个string类型的属性value和color
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface MyAnnotation {
String value();
String color();
}
我们建个测试类来测试一下
package com.example.demo;
import com.example.demo.annotation.MyAnnotation;
/**
* Created by yuxl on 2019/1/16.
* 将我们自定义的注解贴在测试类上,给注解类的两个属性赋值
* 通过测试类得到该类上使用的注解的实例,打印出注解的属性值
*/
@MyAnnotation(value="car",color = "green")
public class TestAnnotation {
public static void main(String[] args){
//检测TestAnnotation类是否有注解
if(TestAnnotation.class.isAnnotationPresent(MyAnnotation.class)){
//获取注解实例
MyAnnotation myAnnotation = TestAnnotation.class.getAnnotation(MyAnnotation.class);
//打印出注解属性
System.out.println("The color is "+ myAnnotation.color()+"! The " + myAnnotation.value()+" can go!");
}
}
}
执行代码,输出打印结果:
更多详细的介绍可以参阅https://www.cnblogs.com/xdp-gacl/p/3622275.html
感谢大家百忙之中抽出宝贵的时间阅读本文,欢迎大家批评指正。微信扫下面二维码添加公众号议码评川,可获取java web、大数据、人工智能等相关学习资料。