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

举报
KevinQ 发表于 2022/04/18 22:11:55 2022/04/18
【摘要】 问题起源最近在学习shiro,shiro中一个很便利很优雅的地方便是可以给方法添加注解,以便控制当前接口内部是否能够被当前登录用户访问。shiro控制样例代码如下: @RequiresPermissions("all") public void test() { renderText("测试"); }这行代码的作用是:限制只有拥有all权限的用户才可以访问该接口,否则会抛出异常。那么问题...

问题起源

最近在学习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库帮助我们实现的注解,分别有TargetRetentionDocumentedInherited

分别表示:

@Target

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

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编程,我们慢慢展开来讲。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。