java注解(一)

什么是注解?

用一个词就可以描述注解,那就是元数据,即一种描述数据的数据。所以,可以说注解就是源代码的元数据。

@Override

public String toString() {

    return "This is String Representation of current object.";

}

@Override告诉编译器这个方法是一个重写方法(描述方法的元数据)

 

为什么要引入注解?

使用Annotation之前(甚至在使用之后),XML被广泛的应用于描述元数据。

但是广泛xml后,开发人员发现XML的维护越来越困难了。

他们希望有一个和代码紧耦合的东西来做代码描述,而不是全部使用XML这种和代码松耦合的描述。

 

那么问题来了,什么时候使用注解,什么时候使用xml?

我们再来回顾一下上面两种配置方式的特点:

  • 对于注解的方式。我们会发现它和代码结合得很紧密,所以注解比较适合做一些与代码相关度高的操作,例如将Bean对应的服务暴露出去。
  • 对于XML配置方式。我们会发现它将配置和代码隔离开来了所以XML配置更适合做一些全局的、与具体代码无关的操作,例如全局的配置等。

我相信很多人此前对于注解的认识就是方便开发。但事实上使用注解还是XML的判断标准应该是:该配置与代码的相关度。如果代码与配置相关度高,那么使用注解配置,否则使用XML配置。

 

注解的作用

生成文档。这是最常见的,也是java 最早提供的注解。常用的有@see @param @return

跟踪代码依赖性,实现替代配置文件功能。比较常见的是spring 2.5 开始的基于注解配置。作用就是减少配置。现在的框架基本都使用了这种配置来减少配置文件的数量。

在编译时进行格式检查。如@Override 放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出。

注解在目前而言最主流的应用:代替配置文件

注解的优缺点

注解优点:开发效率高 成本低 

注解缺点:耦合性大 并且不利于后期维护

注解是如何生成并使用的?

第一步:自定义注解

第二步:使用注解

第三步:解析注解

Annotations仅仅是元数据,和业务逻辑无关。

如果Annotations不包含业务逻辑,那么必须有人来实现这些逻辑。元数据的"使用者"来做这个事情。Annotations仅仅提供它定义的属性(类/方法/包/域)的信息。Annotations的"使用者"来读取这些信息并实现必要的逻辑。当我们使用框架提供的注解时,框架中的某个组件会负责做读取后的逻辑处理。

框架一般都帮我们实现了第一步自定义注解,和第三步解析注解,我们日常开发过程中用到的基本都是第二步,使用注解。

 

自定义注解

一个注解大致可以分为三个部分:注解体、元注解、注解属性

注解体指定了注解的名字

元注解标记了该注解的使用场景、留存时间等信息

而注解属性则指明该注解拥有的属性。

7dd2eb021d68ddf8be3661d7f495feca7eb.jpg

 

注解体

注解体是最简单的一个组成部分,只需要实例中一样有样学样即可。与接口的声明唯一的不同是在 interface 关键字前多了一个 @ 符号。

//声明了一个名为sweet的注解体

@Retention(RetentionPolicy.RUNTIME)

public @interface sweet{

}

元注解

元注解(meta-annotation)本身也是一个注解,用来标记普通注解的存留时间、使用场景、继承属性、文档生成信息。

元注解是一个特殊的注解,它是 Java 源码中就自带的注解。在Java 中只有四个元注解,它们分别是:@Target、@Retention、@Documented、@Inherited。

@Target注解

Target 注解限定了该注解的使用场景。

它有下面这些取值:

  • ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
  • ElementType.CONSTRUCTOR 可以给构造方法进行注解
  • ElementType.FIELD 可以给属性进行注解
  • ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
  • ElementType.METHOD 可以给方法进行注解
  • ElementType.PACKAGE 可以给一个包进行注解
  • ElementType.PARAMETER 可以给一个方法内的参数进行注解
  • ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})

public @interface Autowired {

        boolean required() default true;

}

在上面 Autowire的 注解中,其 Target 注解的值为 CONSTRUCTOR、METHOD、PARAMETER、FIELD、ANNOTATION_TYPE 这 5 个值。这表示 Autowired 注解只能在构造方法、方法、方法形参、属性、类型这 5 种场景下使用。

@Retention注解

Retention 注解用来标记这个注解的留存时间。

它其有四个可选值:

  • RetentionPolicy.SOURCE。注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。
  • RetentionPolicy.CLASS。注解只被保留到编译进行的时候,它并不会被加载到 JVM 中。
  • RetentionPolicy.RUNTIME。注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们。

@Retention(RetentionPolicy.RUNTIME) public @interface Autowired { boolean required() default true; }

在上面 Autowire的 注解中,其 Retention 注解的值为 RetentionPolicy.RUNTIME,说明该注解会保留到程序运行的时候。

@Documented

@ Documented 注解表示将注解信息写入到 javadoc 文档中。

在默认情况下,我们的注解信息是不会写入到 Javadoc 文档中的。但如果该注解有 @Documented 标识,那么该注解信息则会写入到 javadoc 文档中。

@Inherited

@ Inherited注解标识子类将继承父类的注解属性。

在下面的例子中,我们声明了一个 Sweet 注解,接着在 Peach 类使用了 @Sweet 注解,但是并没有在 RedPeach 类使用该注解。

//声明一个Sweet注解,标识甜味。

@Inherited

@Retention(RetentionPolicy.RUNTIME)

@interface Sweet {}

//桃子有甜味

@Sweet

public class Peach {}

//红色的水蜜桃

public class RedPeach extends Peach {}

虽然我们没在 RedPeach 类上使用了 @Sweet 注解,但是我们在 Sweet 注解声明中使用了 @Inherited 注解,所以 RedPeach 继承了 Peach 的 @Sweet 注解。

注解属性

注解属性类似于类方法的声明,注解属性里有三部分信息,分别是:属性名、数据类型、默认值。

在 @Autowired 注解中就声明了一个名为 required 的 boolean 类型数据,其默认值是 true。

public @interface Autowired { boolean required() default true; }

需要注意的是,注解中定义的属性,它的数据类型必须是 8 种基本数据类型(byte、short、int、long、float、double、boolean、char)或者是类、接口、注解及它们的数组。

 

注解解析

       何为解析注解?即通过反射获取类、函数或成员上的运行时注解信息,从而实现动态控制程序运行的逻辑。

解析注解主要用到两个类库:

1.1.  java.lang.annotation.Annotation

Java使用Annotation接口来代表程序元素前面的注解,该接口是所有Annotation类型的父接口。

1.2. java.lang.reflect.AnnotatedElement

AnnotatedElement 接口代表程序中可以接受注解的程序元素,是所有程序元素(Class、Method、Field、Package和Constructor)的父接口。获取该接口对象之后,即可以调用对象方法来访问AnnotatedElement信息,常用有如下几个:

         1. getAnnotations():返回该程序元素上存在的所有注解。

         2. isAnnotationPresent(annotation.class):判断该程序元素上是否包含指定类型的注解

         3. getDeclaredAnnotations():返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注释。

 

案例:通过注解自动生成sql(表的创建)

第一步:自定义注解

表名称的注解

e53ee1a7f1a340da7f109ad058669fd7b8b.jpg

表属性的注解

22b1e076e20b54c6e7f7dfbe5ef6bed8457.jpg

第二步:使用注解

1bdd8933050df9c751c895a7558f9311343.jpg

 

第三步:解析注解

cf27e9457208417f1e61e8b259a28f89bd4.jpg

0c312bae57b5b1d340706e1b45f535b8eb1.jpg

a1ef03c3218f9caec513f94f1ff229e6b85.jpg

转载于:https://my.oschina.net/jiangbang/blog/3078168

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值