如何实现Java注解—元注解与自定义注解的基本格式

网友投稿 814 2022-05-30

问题起源

最近在学习shiro,shiro中一个很便利很优雅的地方便是可以给方法添加注解,以便控制当前接口内部是否能够被当前登录用户访问。

shiro控制样例代码如下:

@RequiresPermissions("all") public void test() { renderText("测试"); }

这行代码的作用是:限制只有拥有all权限的用户才可以访问该接口,否则会抛出异常。

那么问题来了,如何实现Java中非常优雅的注解这种形式呢?

注解的实现原理

注解的实现是基于反射原理的。

Talk is Cheap, Show me your Code!

一个注解的实现过程

下面我们将逐步尝试实现一个我们自己的注解,比如我们叫它MyAnno,他的作用就是在其注解的方法执行前输出一段指定的文字。

实现注解,首先需要有一个被标记为@interface的接口。

public @interface MyAnno { }

在Java中还有四种注解被称为元注解,即Java库帮助我们实现的注解,分别有Target, Retention,Documented,Inherited

分别表示:

@Target

修改其他注解类,标注当前注解会被用在什么地方,使用样例如:@Target({ElementType.TYPE, ElementType.METHOD})。括号中可选的参数可以参考java.lang.annotation.ElementType,我们说几个例子:

如何实现Java注解—元注解与自定义注解的基本格式

ElementType.TYPE:表示类注解,类型注解

ElementType.FIELD:字段注解

ElementType.METHOD:方法注解

ElementType.PARAMETER:参数注解

ElementType.CONSTRUCTOR:构造方法注解

ElementType.LOCAL_VARIABLE:局部变量注解

ElementType.ANNOTATION_TYPE:注解的注解

ElementType.PACKAGE:包注解

比如,我们准备定义的MyAnno为方法注解,则有:

@Target(ElementType.METHOD) public @interface MyAnno { }

@Rentention

表示当前注解的运行状态,可取值参见java.lang.annotation.RetentionPolicy:

RetentionPolicy.SOURCE:其注释为将被编译器丢弃,只在源码运行;

RetentionPolicy.CLASS:编译类文件是运行;

RetentionPolicy.RUNTIME:运行时运行。

比如,我们定义的MyAnno,需要添加代码如下:

@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MyAnno { }

@Documented

该注解为生成说明文档,添加类的解释,不多说,我们暂且略过。

@Inherited

表示允许子类继承父类中的继承,我们也暂且略过。

到这里我们的注解就定义完了。我们来尝试使用以下,仅仅是使用,还没到运行的时候。

public class TestAnno { @MyAnno public void testAnno() { System.out.println("testAnno方法内部"); } public static void main(String[] args) { new TestAnno().testAnno(); } }

这段代码可以编译通过,没有报错,并且执行也没有问题,当然,现在我们的注解还没有添加动作。

那么,怎么给注解添加指定动作呢?

最最关键的内容:注解执行器

注解执行器才是注解中最关键的内容,上面的代码仅仅是告诉我们,告诉编译器与jvm,这个方法被我们标记了。但是具体怎么执行,还是要看注解执行器的。但是执行器设计到反射,复杂的执行器还涉及到AOP编程,我们慢慢展开来讲。

Java

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:dede:list及dede:arclist 按权重排序的方法
下一篇:dmhsq-vue3-vite-electron Version0.0.1
相关文章