我知道你用过Annotation,那你知道它的底层实现吗

网站建设2年前发布
35 00

注解想必大家在项目中经常使用,比如Spring框架中常用的一些注解:@Controller、@Service、@RequestMapping等等,它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。,根据注解的使用场景,主要分为三类,元注解、内置注解和自定义注解。,用于定义注解的注解,通常用于注解的定义上,标明该注解的使用范围、生效范围等。简而言之,元注解是用来修饰注解的。,指定注解信息保留到哪个阶段,分别为源代码阶段、编译Class阶段、运行阶段。,指定注解的使用范围,如类、方法、属性、局部属性、参数等, 可以多选。,具体可选的枚举如下:,加上该注解的注解,表示可以被标注的类子类继承,比如A上标记了带有@Inherited 的注解,那么类B继承了A, 那么B也会有这个注解,默认情况下注解是不支持继承的。,将此注解包含在 javadoc 中 ,它代表着此注解会被javadoc工具提取成文档。,1.8中加入的元注解,用来标记是否可以重复标记。,java提供了一些内置注解,可以配合编译器来检查代码的正确性, 我们可以关注他们的元注解。,标记当前方法是覆写父类的方法。,标记一个元素为已过期,不要在使用了,用来关闭编译器输出的警告信息,java8中引入,标记是一个函数式接口,也就是说有且只有一个抽象方法的接口,注解遵循的格式一般如下:,举个项目中自定义的栗子:,大部分情况下,我们的项目或者开源框架中都定义了大量的注解,而且都是@Retention(RetentionPolicy.RUNTIME)运行时阶段,我们可以通过反射获取注解中的信息,所以整体遵循下面的一个范式。,下面我们重点使用下如何用反射来获取注解的信息。,大家有没有想过注解的本质是什么?,我们先通过反编译查看注解生成的字节码,可以通过javap -v FullAnnoTest.class查看如下:,我知道你用过Annotation,那你知道它的底层实现吗,可以看到,我们的注解是继承自Annotation接口。,所以注解相当于一个语法糖一样,可以方便我们使用,本质上它是继承自Annotation的一个接口。,那大家有没有想过它的实现类在哪里?比如下面的代码,获取到注解,按照上面的解释,它是一个接口,那调用value()方法时,它具体调用的哪个实现类呢?我们并没有写实现类啊…..,答案当然就是动态代理生成的实现类。,我们可以在启动参数添加如下命令可以查看生成的代理类:
-Dsun.misc.ProxyGenerator.saveGeneratedFiles=true,我知道你用过Annotation,那你知道它的底层实现吗,执行后,生成代理类如下,,我知道你用过Annotation,那你知道它的底层实现吗,代理大致的代码如下:,我们看value()方法,这里调用了super.h对象,也就是InvocationHandler对象,而我们注解用的是AnnotationInvocationHandler这个子类,我们在invoke方法中打个断点,就明白了~~

© 版权声明

相关文章