从头学习java的注解

注解是从JDK1.5以后引入的,现在它早已经成为JAVA开发平台中非常重要的一部分。对于稍有经验的开发工程师来说,我们在平时工作中都大量运用的注解。那么我们不禁要提出这样的疑问:

1.那么注解是什么?
2.JAVA为什么要引入注解?
3.注解的本质是什么?
4.我们平时都有哪些常见的注解?
5.我们如何编写自定义的注解?

一、什么是注解

Annontation,中文成为注解,它提供可一种安全的雷石玉注释的机制,用来将任何的信息或者元数据(metadata)与程序元素(类、方法、变量等)进行关联,为程序的元素加上更加直观明了的说明。Annotation是一种应用于类、方法、参数、变量、构造器及包声明中的特殊修饰符。

二、JAVA为什么要引入注解

我们先举一个例子,在JDK1.5之前,我们要在spring中生命一个bean,就只能采用xml的方式:

<bean id="userServcie" class="com.demo.service"> </bean>

当有了注解之后,我们就可以不用写XML的配置文件,直接在UserService的类上加一个@Service的注解就可以。

   @Service
  public class UserService{
  
  }

从上面的例子中可以看出:

  1. 通过XML的方式,配置和代码被隔离开了,所以XML比较适合做一些全局的、与具体代码无关的配置;
  2. 通过注解的方式,注解和代码紧密结合,所以一些与代码相关都比较高的操作,建议用注解。
    除此之外,我们看到,通过注解的方式进行编码,特别快,大量减少了代码量。
    综上所述,我认为之所以要引入注解:
    1.通过注解的方式进行编码,特别快,大量减少了代码量;
    2.当开发人员希望元数据与代码紧密耦合,使用注解更加方便;

3.注解的本质是什么

上面我们了解了注解的基本概念和简单的示例,那么注解本质上是什么呢?是一个类还是接口呢?我们知道,注解也被称为声明式接口。我这里定一个了一个注解,从它的继承关系看到:

@OperateLog继承了Annotation 接口,那基本就可以确定它是一个接口了。

我们通过它的字节码看到,这里调用了invokeinterface指令,所以这就是一个接口。即注解是一个接口,并且是一个继承自Annotation的接口。

4.我们平时都有哪些常见的注解

4.1 四种元注解

java.lang.annotation提供了四种元注解,专门注解其他的注解,他们分别是:@Documented,@Retention,@Target,@Inherited。下面我们简要说一下:

  • @Documented:它的作用是能够将注解中的元素包含到 Javadoc 中去;
  • @Retention:Retention 的英文意为保留期的意思, @Retention 应用到一个注解上的时候,它解释说明了这个注解的的存活时间。它的取值如下:
    RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。
    RetentionPolicy.CLASS 注解只被保留到编译进行的时候,它并不会被加载到 JVM 中。
    RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们。
  • @Target:Target 是目标的意思,@Target 指定了注解运用的地方。当一个注解被 @Target 注解时,这个注解就被限定了运用的场景,它的取值如下:ElementType.ANNOTATION_TYPE 可以给一个注解进行注解;
    ElementType.CONSTRUCTOR 可以给构造方法进行注解;
    ElementType.FIELD 可以给属性进行注解;
    ElementType.LOCAL_VARIABLE 可以给局部变量进行注解;
    ElementType.METHOD 可以给方法进行注解;
    ElementType.PACKAGE 可以给一个包进行注解;
    ElementType.PARAMETER 可以给一个方法内的参数进行注解;
    ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举。
  • @Inherited:Inherited 是继承的意思,但是它并不是说注解本身可以继承,而是说如果一个超类被 @Inherited 注解过的注解进行注解的话,那么如果它的子类没有被任何注解应用的话,那么这个子类就继承了超类的注解。

4.2 Java 预置的注解

@Deprecated:这个元素是用来标记过时的元素,。编译器在编译阶段遇到这个注解时会发出提醒警告,告诉开发者正在调用一个过时的元素比如过时的方法、过时的类、过时的成员变量,这个注解我们基本都都用到过或者见到过;
@Override:提示子类要复写父类中被 @Override 修饰的方法,这个是我们开发人员平时遇到最多的了;
@SuppressWarnings:阻止或者压制警告,阻止编译器发出警报信息;

5.我们如何编写自定义的注解

这里我做一个简单记录用户操作记录的注解@OperateLog
1.首先定义注解类OperateLog

package com.demo.annotation;

import java.lang.annotation.*;

/**
 * 这是一个自定义注解,标记操作日志
 *
 * @author lxc
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface OperateLog {
    /**
     * 模块
     */
    public String title() default "";

    /**
     * 操作方式
     *
     * @return
     */
    public String businessType() default "更新";

    /**
     * 是否保存方法中的参数
     */
    public boolean isSaveParamData() default true;

}

写一个test类解析注解:

import com.demo.annotation.OperateLog;

import java.lang.reflect.Method;

/**
 * 这是一个自定义注解测试类
 *
 * @author lxc
 */
public class OperateLogTest {

    public static void main(String[] args) {
        Method[] declaredMethods = UserService.class.getDeclaredMethods();
        for (Method method : declaredMethods) {
            if (method.isAnnotationPresent(OperateLog.class)) {
                OperateLog operateLog = method.getAnnotation(OperateLog.class);
                System.out.println(operateLog.title() + ":" + operateLog.businessType() + ":" + operateLog.isSaveParamData());
            }
        }
    }
}

运行结果:

用户模块:删除:true
用户模块:新增:true
用户模块:更新:true

在生产中我们结合AOP,在切点处,记录每次的操作记录。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值