1.Annotation介绍  

  Annontation是Java5开始引入的新特征。中文名称一般叫注解。

  Annontation像一种修饰符一样,应用于包、类型、构造方法、方法、成员变量、参数及本地变量的声明语句中。 Java5版本开始,自带了三种标准annontation类型,@Override、@Deprecated和@SuppressWarnings。    

      @Override:用于修饰此方法覆盖了父类的方法;

      @Deprecated:用于修饰已经过时的方法;

      @SuppressWarnnings:用于通知java编译器禁止特定的编译警告。@SuppressWarnnings与上两个注解不同的地方是,上面2个注解不需要加参数,而@SuppressWarnnings需要加上参数,例如可以在方法的前面加上

        @SuppressWarnings(value={ "rawtypes", "unchecked" }),使用非泛型的容器类时将不会再出现警告信息。

  除了Java自带的Annontation,我们在框架,比如Spring中会发现Annontation的大量使用,很大程度上简化了代码。

 2.Annontation原理

  Annontation本身不能做任何事情,需要一个类对Annontation进行处理,使用Java的反射机制来获取Annontation中的信息,再执行一些操作。 

  Annotation是不会影响程序代码的执行,无论annotation怎么变化,代码都始终如一地执行。

 3.Annontation基本语法

  了解注解的语法之前,先需要了解元注解。元注解就是可以用于注解的注解,定义了注解可修饰的对象、作用的范围等。

  可以先看看 @Override注解的代码: 

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

   Java5版本中定义的元注解包括: 

          @Target、@Retention、@Documented、@Inherited

   @Target: 注解可修饰的对象,例如是方法还是变量。@Target的取值包括如下:

    ElementType.METHOD:  可用法方法

    ElementType.TYPE:  可用于类或者接口

    ElementType.CONSTRUCTOR:  可以用于构造方法等

    ...

  @Retention:   注解的作用范围:

    RetentionPolicy.RUNTIME:   运行时有效

    RetentionPolicy.SOURCE:    在Java类中有效

    RetentionPolicy.CLASS:        在class文件中有效

  @Documented:   用于使用javadoc生成的文档上将显示注解的信息

    eclipse中生成javadoc的方法,选中类或者工程,右键export,选择javadoc,往下继续执行即可。

生成的javadoc中的截图如下:

  

  @Inherited:  @Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。

  了解了元注解之后,就可以试着自己写一个注解了。

  注解的格式:  public @interface 注解名 {定义体}

  @interface用于声明一个注解,定义体中能出现的数据类型包括: 基本类型、String、Class、enum和以上类型的数组。

  

  下面是一个注解和怎样处理注解的例子:

  水果名称注解:  

package annotation;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 水果名称注解 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitName {String value() default "";
}

  水果颜色注解:

package annotation;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 水果颜色注解*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitColor {/*** 颜色枚举* @author peida**/public enum Color{ BULE,RED,GREEN};/*** 颜色属性* @return*/Color fruitColor() default Color.GREEN;}

  水果供应者注解 :

package annotation;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/*** 水果供应者注解**/@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface FruitProvider {/*** 供应商编号* @return*/public int id() default -1;/*** 供应商名称* @return*/public String name() default "";/*** 供应商地址* @return*/public String address() default "";}

  将以上的注解用于Apple类:

public class Apple {@FruitName("Apple")private String appleName;@FruitColor(fruitColor=Color.RED)private String appleColor;@FruitProvider(id=1,name="陕西红富士集团",address="陕西省西安市延安路89号红富士大厦")private String appleProvider;public void setAppleColor(String appleColor) {this.appleColor = appleColor;}public String getAppleColor() {return appleColor;}public void setAppleName(String appleName) {this.appleName = appleName;}public String getAppleName() {return appleName;}public void setAppleProvider(String appleProvider) {this.appleProvider = appleProvider;}public String getAppleProvider() {return appleProvider;}public void displayName(){System.out.println("水果的名字是:苹果");}
}

  写一个处理注解的类,没有该类,只单单的存在注解,是不起任何作用的:

public class FruitInfoUtil {public static void getFruitInfo(Class<?> clazz){String strFruitName=" 水果名称:";String strFruitColor=" 水果颜色:";String strFruitProvicer="供应商信息:";Field[] fields = clazz.getDeclaredFields();for(Field field :fields){if(field.isAnnotationPresent(FruitName.class)){FruitName fruitName = (FruitName) field.getAnnotation(FruitName.class);strFruitName=strFruitName+fruitName.value();System.out.println(strFruitName);}else if(field.isAnnotationPresent(FruitColor.class)){FruitColor fruitColor= (FruitColor) field.getAnnotation(FruitColor.class);strFruitColor=strFruitColor+fruitColor.fruitColor().toString();System.out.println(strFruitColor);}else if(field.isAnnotationPresent(FruitProvider.class)){FruitProvider fruitProvider= (FruitProvider) field.getAnnotation(FruitProvider.class);strFruitProvicer=" 供应商编号:"+fruitProvider.id()+" 供应商名称:"+fruitProvider.name()+" 供应商地址:"+fruitProvider.address();System.out.println(strFruitProvicer);}}}  

public static void main(String[] args) {

getFruitInfo(Apple.class);

}
}

  输出结果为;

水果名称:Apple水果颜色:RED供应商编号:1 供应商名称:陕西红富士集团 供应商地址:陕西省西安市延安路89号红富士大厦

  

  

  注解的处理通常有两种方式:在编译时、或在运行时。

  Java5使用的apt工具(JDK的bin目录下由apt.exe)和Oracle私有的Mirror API工具已经在Java7中被声明为废弃。

  Java6引入了Pluggable Annotaion Processing API,对注解处理机制进行了标准化。

    a、分析注解,比如统计一个有多少个类加载了某个注解。(编译时)

    b、根据注解,创建和修改源代码(运行时)

    c、使用反射处理注解(运行时)

 4.和反射、动态代理结合使用

  应用场景:把注解、反射和动态代理结合起来。注解用来设置运行时的行为,反射API用来解析注解,动态带来负责应用的具体行为。

  例子:模拟权限管理

  Role注解:  

package annotation.withreflect;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Role{String[] value();
}

  使用JDK的代理,需要一个接口:

package annotation.withreflect;public interface EmployeeInfoManager{@Role("manager")public void updateSalary();
}

  接口的具体实现:

package annotation.withreflect;public class DefaultEmployeeInfoManager implements EmployeeInfoManager{@Overridepublic void updateSalary() {System.out.println("manager update Salary!");}}

  写一个模拟获取角色的类,将随机获取到manager和employee角色:

package annotation.withreflect;import java.util.Random;public class AccessManager {public static String getCurrentUserRole(){String role = "manager";Random rd = new Random();int i = rd.nextInt(46);System.out.println("random int: " + i);if(i%2==0){role = "employee";}        return role;}
}

  使用反射、动态代理来处理注解,只有manager角色可以调用updateSalary方法,:

package annotation.withreflect;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;public class EmployeeInfoManagerProxy implements InvocationHandler {private final Object targetObject;public EmployeeInfoManagerProxy(Object targetObject) {this.targetObject = targetObject;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Role annotation = method.getAnnotation(Role.class);if (annotation != null) {String[] roles = annotation.value();String currentRole = AccessManager.getCurrentUserRole();if (!Arrays.asList(roles).contains(currentRole)) {System.out.println("没有调用此方法的权限。");return null;}}return method.invoke(targetObject, args);}public EmployeeInfoManager getManager() {EmployeeInfoManager instance = new DefaultEmployeeInfoManager();return (EmployeeInfoManager) Proxy.newProxyInstance(instance.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);}
}

  写一个测试类:

package annotation.withreflect;public class ReflectTest {public static void main(String[] args) {EmployeeInfoManagerProxy ef = new EmployeeInfoManagerProxy(new DefaultEmployeeInfoManager());EmployeeInfoManager em = ef.getManager();em.updateSalary();}
}

  运行结果为:

random int: 4
没有调用此方法的权限。///或者如下:
random int: 23
manager update Salary!

转载于:https://www.cnblogs.com/lnlvinso/p/4521170.html

Annotation基础知识相关推荐

  1. 基础知识漫谈(1): 想到哪儿写到哪儿

    http://www.cnblogs.com/anrainie/p/5606570.html ***************************** 一.想到哪儿写到哪儿 给公司新员工培训,和网上 ...

  2. 第76节:Java中的基础知识

    第76节:Java中的基础知识 设置环境,安装操作系统,安装备份,就是镜像,jdk配置环境,eclipse下载解压即可使用,下载tomcat 折佣动态代理解决网站的字符集编码问题 使用request. ...

  3. (硅谷课堂项目)Java开发笔记4:前端基础知识(二)

    文章目录 (硅谷课堂项目)Java开发笔记4:前端基础知识(二) 一.NPM 1.NPM简介 1.1.什么是NPM 1.2.NPM工具的安装位置 2.使用npm管理项目 2.1.创建文件夹npm 2. ...

  4. SpringBoot基础知识

    SpringBoot基础知识 SpringBoot课程笔记 前言 ​ 很荣幸有机会能以这样的形式和互联网上的各位小伙伴一起学习交流技术课程,这次给大家带来的是Spring家族中比较重要的一门技术课程- ...

  5. 我就不信了,spring基础知识这么总结整理还拿不下大厂offer(一)

    本人作为一个学渣,大学四年醉生梦死,得过且过,学习知识虽不至于什么都不懂,但基本上是浮于表面.虽然度过一个愉快的大学生活,但最终却不得不为自己当初的任性买单,投递简历四处碰壁,看着身边的同学一个个每天 ...

  6. JavaWebJavaEE重要基础知识

    最新版JavaEE&JavaWeb知识详解 前言 JavaWeb和JavaEE的区别 JavaWeb的框架 JavaWeb模式 JavaWeb的架构 JavaEE规范 文件结构 开发规则 前言 ...

  7. linux下tc、htb、iptables基础知识及openwrt 下qos使用介绍

    htb基础知识:Linux Htb队列规定指南中文版:http://wenku.baidu.com/view/64da046825c52cc58bd6beac.html TC基础知识: Linux 的 ...

  8. java基础知识之注解、反射(一)

    前言 此博客为供个人学习总结备用,如有错误请指正. 正文 Annotation(注解) java自带的注解包含以下三个: 1.@Override 注解表示重写父类的方法 2.@Deprecated 声 ...

  9. C#进行MapX二次开发之MapX基础知识

    C#进行MapX二次开发之MapX基础知识 MapX的主要技术特点 (1). 以表(Table)的形式组织信息 每一个表都是一组MapInfo文件,这些文件组成了地图文件和数据库文件.为使用MapIn ...

最新文章

  1. ASP.NET MVC 5 - 视图
  2. 删除ctrl alt del更改密码
  3. SQLyog中TAB键设置四个空格的步骤
  4. 7项最佳实践助您利用媒体转换不断发展数据中心网络
  5. php serialize取值,PHP 序列化(serialize)格式详解
  6. 834 树中距离之和
  7. TortoiseGit 修改密码
  8. linux mutt 使用指南,linux mutt详解
  9. 【每日一读】EMNLP2020: 面向多跳问答的分层图网络
  10. Linux安装软件包时的“依赖关系树”算法(C#)
  11. 交易系统开发(七)——交易延迟分析
  12. 安装与配置SVN版本控制器(汉化包)
  13. 《炬丰科技-半导体工艺》 砷化硼热管理
  14. phpstudy编写php扩展,PHP_探讨:如何编写PHP扩展,用C/C++扩展PHP的优缺点:优点 - phpStudy...
  15. Altium Designer简明教程2
  16. 计算机组装论文1000字,计算机组装
  17. JER与JDK区别以及JDK的安装配置(2021-06-13 Win10)
  18. linux 查看磁盘、文件夹、文件大小(df du)
  19. Redis的五种数据结构原理分析(中)
  20. [转]提交表单后 PHP获取提交内容 的方法

热门文章

  1. gjrand 4.0 发布,C语言的伪随机数生成器
  2. thinking in java(第七章)
  3. 王秋杨的“前世”和她的“在路上”
  4. 1.8 centos7网络排错
  5. 搞不清FastCgi与PHP-fpm之间是个什么样的关系
  6. sql server2008如果表中已经有很多条记录,再添加一个非空字段
  7. Report_客制化报表输出Excel后去0问题(案例)
  8. git reset简介
  9. 关于在Winphone中使用Google Map的问题(徐林峰)
  10. outlook常见错误分析指南