java基础-注解Annotation原理和用法

时间:2021-07-12 12:20:49

在很多java代码中都可以看到诸如@Override、@Deprecated、@SuppressWarnings这样的字符,这些就是注解Annotation。注解最早在jdk5中被引入,现在已经成为java平台很重要的一部分了,很多的框架程序中也喜欢使用注解,如Spring、Mybatis等。

那么,什么是注解呢?注解就是元数据,一种描述数据的数据,通俗一点就是为程序的元素(类、方法、成员变量)加上更直观的说明,这些说明信息是与程序的业务逻辑无关的。但是,我们可以通过java的反射机制来获取Annotation的信息,并根据这些信息来对程序进行赋值、分发等操作。
 
java5.0定义了4个标准的meta-annotation元注解,它们被用来提供对其它annotation类型作说明,四种元注解如下:
  • @Target;
  • @Retention;
  • @Inherited;
  • @Documented;
 
下面详细说明这四种元注解的作用:
@Target
被用于描述注解的使用范围,即注解可以用在所修饰对象的什么地方,取值可以是ElementType中的一种:
  • CONSTRUCTOR:用于描述构造器;
  • FIELD:用于描述域;
  • LOCAL_VARIABLE:用于描述局部变量;
  • METHOD:用于描述方法;
  • PACKAGE:用于描述包;
  • PARAMETER:用于描述参数;
  • TYPE:用于描述类、接口、注解类型或枚举;
@Target(ElementType.TYPE)
public @interface Exculde{
/**
* 名称,默认值为""
* @return
*/
public String name() default "";
} @Target(ElementType.FIELD)
public @interface Inject{
/**
* id,默认值为""
* @return
*/
public String id() default ""; /**
* 类,默认值为""
* @return
*/
public Class clazz() default Object.class; }
上面定义了两个注解,注解@Exculde只能用于修饰类、接口、注解、枚举,注解@Inject只能修饰类型的域,如:
@Exculde(name="admin")
public class User{
@Inject(id="username",clazz=String.class)
private String username;
}
 
@Retention
用于描述注解的生命周期,即注解能在源码到JVM装载过程中的哪一个级别上有效。有些annotation仅出现在源码中,被编译器丢弃;有些annotation能被编译进class文件中,可能被JVM忽略;有些annotation不但能够被编译进class文件,而且能够在class文件被装载时被读取。这三种情况对应RetentionPoicy的三种取值:
  • SOURCE:源码文件中保留;
  • CLASS:class文件中保留;
  • RUNTIME:运行时保留;
 
@Inherited
用于描述注解是可以被继承的,如果一个使用了@Inherited修饰的annotation被用于一个class,那么这个annotation也将被用于这个class的子类。@Inherited是一个标记注解,没有参数选项,它修饰的annotation是被标记的class的子类所继承,类并不从它所实现的接口继承annotation,方法并不从它所重载的方法继承annotation。
     当使用java的反射去获取一个@Inherited修饰的annotation时,反射检查将递归检查,检查class和其父类,直到发现指定的annotation类型被发现,或者到达类继承结构的顶层。
 
@Documented
    用于描述注解信息应该被作为被标注的程序的公共API,即应该把注解信息保留文档中。@Documented也是一个标记注解,没有参数选项。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Exculde{
/**
* 名称注解,默认值为""
* @return
*/
public String name() default "";
}
如果你看过了上面的元注解,如果还不能理解也没关系,下面我们通过自定义注解来进一步理解元注解。
 
自定义注解需要使用@interface,类似于定义一个类使用class,但定义注解时不能再继承其它的类或者接口,它已经自动继承了java.lang.annotation.Annotation接口。@interface用来声明一个注解,其中的每一个方法实际上声明了一个配置参数,方法的名称就是参数的名称,方法的返回值类型就是参数的类型,也可以使用default来声明参数的默认值。
 
定义注解的格式如下:
public @interface 注解名{ 定义体 }
 
注解参数可支持的数据类型如下:
  • 基本类型;
  • Class;
  • String;
  • Enum;
  • Annotation;
  • 以上所有类型的数组形式;
下面定义一个类似于Spring的注解,用于向实例对象注入属性的值:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Inject{
/**
* ID,默认值为""
* @return
*/
public String id() default ""; /**
* 类,默认值为""
* @return
*/
public Class clazz() default Object.class; }
把@Inject标注在类UserAction的属性上:
public class UserAction {
@Inject(id="userService",clazz=UserService.class)
private UserService userService;
}
在IOC容器框架中,对象都会被自动初始化,如果我们要实现IOC的这种功能,我们应该为加上@Inject注解的属性userService注入它的值。首先我们应该通过反射获取userService的域对象field,通过field获取@Inject注解的信息,然后根据注解的id和clazz得到它依赖的值:
Inject inject = field.getAnnotation(Inject.class);
String id = inject.id();
Class clazz = inject.clazz(); Object userService = Class.forName(clazz.getName).newInstance();
field.setAccessible(true);
field.set(object,userService);
上面代码中,调用field.getAnnotation(Inject.class)获取到@Inject的对象,然后获取@Inject的id和clazz值,通过反射实例化clazz的对象,再反射赋值给field。这就是Spring那些框架的依赖注入的实现原理,有兴趣的可以自己再优化一下。
 
读取类的注解信息还有其它的几个方法,在此不再一一说明,可以自行研究java.lang.reflect包。经过上面的说明,由此我们也可以知道注解仅仅是一种元数据,增强类、属性、参数的描述,使用注解的关键在于获取注解的信息,再通过反射的手段来实现注解想达成的功能。
 
 
 
文章同步发布在朗度云网站,传送门:

java基础-注解Annotation原理和用法的更多相关文章

  1. java基础—注解annotation

    一.认识注解 注解(Annotation)很重要,未来的开发模式都是基于注解的,JPA是基于注解的,Spring2.5以上都是基于注解的,Hibernate3.x以后也是基于注解的,现在的Struts ...

  2. Java基础--注解Annotation

    Annotation是给类,方法或域上加的一种特殊的标记,可以通过反射取到注解的类型和值,从而完成某种特定的操作. 定义注解需要使用元注解,元注解有@Retention和@Target //@Rete ...

  3. Java 基础 —— 注解 Annotation

    简介 Annotation 是从 JDK 5.0 引入的. 注解使得我们可以以编译器验证的格式存储程序的额外信息.注解可以生成描述符文件,甚至是新的类定义,并且有助于减轻编写"样板&quot ...

  4. Java基础笔记 – Annotation注解的介绍和使用 自定义注解

    Java基础笔记 – Annotation注解的介绍和使用 自定义注解 本文由arthinking发表于5年前 | Java基础 | 评论数 7 |  被围观 25,969 views+ 1.Anno ...

  5. Java Android 注解(Annotation) 及几个常用开源项目注解原理简析

    不少开源库(ButterKnife.Retrofit.ActiveAndroid等等)都用到了注解的方式来简化代码提高开发效率. 本文简单介绍下 Annotation 示例.概念及作用.分类.自定义. ...

  6. 再探java基础——break和continue的用法

    再探java基础——break和continue的用法 break break可用于循环和switch...case...语句中. 用于switch...case中: 执行完满足case条件的内容内后 ...

  7. Java并发-volatile的原理及用法

    Java并发-volatile的原理及用法 volatile属性:可见性.保证有序性.不保证原子性.一.volatile可见性 在Java的内存中所有的变量都存在主内存中,每个线程有单独CPU缓存内存 ...

  8. Java:注解Annotation(元数据)

    本文内容: 注解Annotation的介绍 基本注解的用法 自定义注解 首发日期:2018-07-28 注解Annotation的介绍 Annotation是代码中的特殊标记,能够在编译.类加载.运行 ...

  9. Java中注解Annotation的定义、使用、解析

    此例子,用于说明如何在Java中对“注解 Annotation”的定义.使用和解析的操作.注解一般用于自定义开发框架中,至于为什么使用,此处不作过多说明,这里只说明如何使用,以作备记.下面例子已测试, ...

随机推荐

  1. Titanium.App.Properties 对象

    Titanium.App.Properties是用来管理键值对数据的一个很方便的对象.在保存数据的时候,在Ti.App.Properties.setString相对应的Key的值中设置你要保存的值即可 ...

  2. eclipse导入svn项目,项目却没有svn的标记

    现象: eclipse(已经装有svn插件)导入svn项目,项目没有svn的标记. 原因: 1.可能是由于你的svn eclipse插件,也就是subclipse,与svn的客户端版本不匹配. 解决 ...

  3. 历时一年,我的著作《第一行代码——Android》已出版!

    前言 事实上我当初决定開始写博客的想法挺简单的,认为自己搞技术这么多年了,总应该要留下点什么.既然没能写出什么出色的应用,那至少也要留下点文字分享给大家,以指引在我后面的开发人员们,毕竟我也从前辈们的 ...

  4. scu - 3254 - Rain and Fgj(最小点权割)

    题意:N个点.M条边(2 <= N <= 1000 , 0 <= M <= 10^5),每一个点有个权值W(0 <= W <= 10^5),现要去除一些点(不能去掉 ...

  5. 基于DDD的&period;NET项目搭建

    第一次写博客有点小激动,废话不多说先上图: 01_Client:存放UI相关的项目,比如ASP.NET MVC或者相关的Web Model及View Model项目. 02_Hosting:存放与Se ...

  6. ubuntu中的apache的基本技巧

    1. 显示apache的版本号 XXX@XXX-ThinkPad-Edge-E431:~$ apache2 -v Server version: Apache/ (Ubuntu) Server bui ...

  7. LeetCode 7&period; Reverse Integer(c语言版)

    题目: Given a 32-bit signed integer, reverse digits of an integer. Example 1: Input: 123Output: 321 Ex ...

  8. NPOI 操作Word

    /// <summary> /// 替换word中指定内容 /// </summary> /// <param name="wordPath"> ...

  9. Saddle Point ZOJ - 3955(求每个值得贡献)

    题意: 给出一个矩阵,删掉一些行和列之后 求剩下矩阵的鞍点的总个数 解析: 对于每个点 我们可以求出来 它所在的行和列  有多少比它大的 设为a 有多少比它小的 设为b 然后对于那些行和列 都有两种操 ...

  10. Python基本数据类型以及字符串

    基本数据类型                数字  int ,所有的功能,都放在int里            a1 = 123            a1 = 456                 ...