注解是java5引入的特性,在代码中插入一种注释化的信息,用于对代码进行说明,能够对包、类、接口、字段、方法参数、局部变量等进行注解。注解也叫元数据(meta data)。这些注解信息能够在编译期使用预编译工具进行处理(pre-compiler tools),也能够在运行期使用 Java 反射机制进行处理。
它主要的做用有如下四方面:java
通常注解能够分为三类:app
@Override
、@Deprecated
和@SuppressWarnings
,分别用于标明重写某个方法、标明某个类或方法过期、标明要忽略的警告,用这些注解标明后编译器就会进行检查。@Retention
、@Target
、@Inherited
、@Documented
,@Retention
用于标明注解被保留的阶段,@Target
用于标明注解使用的范围,@Inherited用于标明注解可继承,@Documented
用于标明是否生成javadoc文档。为何在类、方法上加一个注解,就能够经过getAnnotation()获取到申明的注解的值?
好比:ide
@Test("test") public class AnnotationTest { public void test(){ } }
对于注解test就能够在运行时经过AnnotationTest.class.getAnnotation(Test.class)获取注解声明的值。工具
在AnnotationTest类被编译后,在对应的AnnotationTest.class文件中会包含一个RuntimeVisibleAnnotations属性,因为这个注解是做用在类上,因此此属性被添加到类的属性集上。即Test注解的键值对value=test会被记录起来。而当JVM加载AnnotationTest.class文件字节码时,就会将RuntimeVisibleAnnotations属性值保存到AnnotationTest的Class对象中,因而就能够经过AnnotationTest.class.getAnnotation(Test.class)获取到Test注解对象,进而再经过Test注解对象获取到Test里面的属性值。
这里可能会有疑问,Test注解对象是什么?其实注解被编译后的本质就是一个继承Annotation接口的接口,因此@Test
其实就是“public interface Test extends Annotation”,当咱们经过AnnotationTest.class.getAnnotation(Test.class)调用时,JDK会经过动态代理生成一个实现了Test接口的对象,并把将RuntimeVisibleAnnotations属性值设置进此对象中,此对象即为Test注解对象,经过它的value()方法就能够获取到注解值。.net
注解能够经过做用的类型可分为:类注解、方法注解、参数注解、变量注解。代理
类注解
访问类注解的例子:code
Class aClass = TheClass.class; Annotation[] annotations = aClass.getAnnotations(); for(Annotation annotation : annotations){ if(annotation instanceof MyAnnotation){ MyAnnotation myAnnotation = (MyAnnotation) annotation; System.out.println("name: " + myAnnotation.name()); System.out.println("value: " + myAnnotation.value()); } }
此方法获取到的是该类的全部注解,也可指定某一个类:对象
Class aClass = TheClass.class; Annotation annotation = aClass.getAnnotation(MyAnnotation.class); if(annotation instanceof MyAnnotation){ MyAnnotation myAnnotation = (MyAnnotation) annotation; System.out.println("name: " + myAnnotation.name()); System.out.println("value: " + myAnnotation.value()); }
Spring中的@Service``@Controller
便是如此。blog
方法注解继承
public class TheClass { @MyAnnotation(name="someName", value = "Hello World") public void doSomething(){} }
获取方法对象的指定注解:
Method method = ... // 获取方法对象 Annotation annotation = method.getAnnotation(MyAnnotation.class); if(annotation instanceof MyAnnotation){ MyAnnotation myAnnotation = (MyAnnotation) annotation; System.out.println("name: " + myAnnotation.name()); System.out.println("value: " + myAnnotation.value()); }
SpringMVC中的@RequestMapping
便是如此。
参数注解
方法的参数也能够添加注解:
public class TheClass { public static void doSomethingElse( @MyAnnotation(name="aName", value="aValue") String parameter){ } }
访问注解:
Method method = ... //获取方法对象 Annotation[][] parameterAnnotations = method.getParameterAnnotations(); Class[] parameterTypes = method.getParameterTypes(); int i=0; for(Annotation[] annotations : parameterAnnotations){ Class parameterType = parameterTypes[i++]; for(Annotation annotation : annotations){ if(annotation instanceof MyAnnotation){ MyAnnotation myAnnotation = (MyAnnotation) annotation; System.out.println("param: " + parameterType.getName()); System.out.println("name : " + myAnnotation.name()); System.out.println("value: " + myAnnotation.value()); } } }
Mybatis中的@Param
便是如此
变量注解
使用注解:
public class TheClass { @MyAnnotation(name="someName", value = "Hello World") public String myField = null; }
获取注解:
Field field = ...//获取方法对象</pre> <pre> Annotation annotation = field.getAnnotation(MyAnnotation.class); if(annotation instanceof MyAnnotation){ MyAnnotation myAnnotation = (MyAnnotation) annotation; System.out.println("name: " + myAnnotation.name()); System.out.println("value: " + myAnnotation.value()); }
Spring中的@Inject``@Resource
便是如此。