龙空技术网

Java注解的工作原理及如何自定义注解

阿迈达聊技术 511

前言:

如今同学们对“java注解原理”大概比较关注,看官们都需要知道一些“java注解原理”的相关资讯。那么小编同时在网络上网罗了一些关于“java注解原理””的相关文章,希望大家能喜欢,小伙伴们快快来了解一下吧!

Annotation是Java重要的组成部分,从J2SE 5.0时代就已经存在了。在我们的代码中,我们随处可以看到许多注解,例如@Autowired、@Override、@Service。这些注解我们可能非常熟悉,但是注解的作用、工作原理、工作方式以及我们如何自定义注解,我们可能并不熟悉。这篇文章我们就探索一下这些知识点。

1、什么是注解

注解是一种特殊的元数据,元数据是关于数据的数据,所以,注解就是代码的元数据。我们看下面这个例子:

我们用@Override注解toString()方法,说明我们要重写toString()方法。这里,即使我们不用@Override注解,这个方法任然可以正常执行。那注解的好处是什么呢?@Override告诉编译器,子类要重写这个方法,需要按照自己定义的格式输出内容,也就是覆盖了父类的方法,如果父类中没有这个方法,编译器就会报错。

所以,注解是一种特殊的Java构造器,它可以用于装饰类,方法,字段,参数,变量,构造函数或包。

2、为什么要使用注解

在注释之前(甚至之后),XML被广泛用于元数据。但是随着项目中代码量的增大,XML维护变得越来越麻烦。开发人员希望元数据与代码是紧密耦合,而XML与代码之间的耦合非常松散(在某些情况下,几乎是分开的)。

关于使用注解还是基于XML进行标记一直是一个具有争议的话题,对于开发人员来说,记住以下两个原则即可:

1、假设您要设置一些应用程序范围内的常量。在这种情况下,XML是一个更好的选择,因为它与任何特定的代码段都不相关。2、如果要将某个方法作为服务公开,则注解将是一个更好的选择,因为它需要与该方法紧密结合。

另一个重要因素是,注解定义了在代码中定义元数据的标准方式。在注解之前,开发人员使用自己的方式定义元数据,这造成元数据定义混乱。但要注解是标准化的东西,更容易维护。

现在,大多数框架都将XML和注解结合使用,以充分利用两者的积极方面。

3、注解的工作方式

注解仅仅是元数据,不包括任何业务逻辑。那它的使用者是谁呢?像@Override这种注解,JVM是它的使用者,它在字节码级别工作。如果我们自己编写了一个注解,那我们就要去实现它的消费者,否则,我们自定义的注解是没有任何作用的。

4、编写自定义注解

在编写自定义注解的时候,我们首先需要搞清楚几个默认的注解,这几个注解仅仅作用与另一个注解之上。

@Documented

@Documented注解表明这个注解要被javadoc记录。注解默认状态下是不被javadoc记录的。

@Retention

@Documented注解表明该注解保留到那个阶段,主要有三个值:

SOURCE —— 这种注解保留在源代码级别,编译时就会被忽略

CLASS —— 这种注解编译时被保留,在class文件中存在,但JVM将会忽略

RUNTIME —— 这种注解将被JVM保留,利用反射机制可以获取并使用。

@Target

@Target注解表明该注解作用的范围。包括package、method、field、构造方法、成员变量、枚举值等属性。

@Inherited

@Inherited注解表明该注解是否影响子类。如果定义的注解上使用了@Inherited标记,则使用该注解的某个父类,它的子类默认继承所有的属性

现在我们定义自己的一个注解@CronScheduled

CronScheduled注解上用了三个默认的注解,@interface表明这是一个注解(注意不是接口)。同时我们定义了cron和desc两个属性。这就是一个完整的注解,我们再看怎么使用它。

我们假设一个业务场景:我们的业务中很多个定时任务,这些定时任务我们手动实现了线程池维护并调度这些方法。那在线程池中我们怎么获取那些方法是定时任务呢?这就是自定义注解的作用。我们在synCreative的方法上使用了我们自定义的注解,目的就是让调度的线程池可以发现它。具体的实现看下面代码:

我们循环遍历所有的定时任务方法,并获取方法上的注解,如果方法上有CronScheduled的注解,说明该方法就是定时任务的方法,同时,获取注解上的cron属性值,设定执行任务的周期。

至此,我们就完成了一个自定义的注解。

5、注解用例

注释功能非常强大,Spring和Hibernate之类的框架将注解广泛用于日志记录和验证,在Servlet规范3.0中,引入了许多注解,尤其是与Servlet安全性相关的注释。让我们看看一些常见的注解。

HandlesTypes 用于声明传递给的应用程序类的数组ServletContainerInitializer。HttpConstraint 被使用来代表应用于所有HTTP协议方法的安全限制HttpMethodConstraint 特定的安全约束可以应用于不同的请求类型MultipartConfig 声明它的Servlet希望使用multipart / form-data MIME类型进行请求。ServletSecurity 在Servlet实现类上声明此注解,以对HTTP协议请求强制实施安全性约束。WebFilter 用于声明Servlet过滤器的注解。WebInitParam 用于在WebFilter或WebServlet上声明初始化参数。WebListener 在给定的Web应用程序上下文中用于声明各种事件的侦听器。WebServlet 用于声明Servlet的配置。

标签: #java注解原理