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)
@Documented
public @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{

    @Override
public 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!

Annotation基础知识的更多相关文章

  1. android反射组件 (一个)java 它们的定义annotation基础知识

    它们的定义annotation它由三部分组成: 它们的定义annotation.使用annotation班.annotation的处理方法. 一.自己定义annotation  元注解包含下面: 1) ...

  2. Spring基础知识

    Spring基础知识 利用spring完成松耦合 接口 public interface IOutputGenerator { public void generateOutput(); } 实现类 ...

  3. JAVAEE规范基础知识

    JavaEE规范基础知识 本人博客文章网址:https://www.peretang.com/basic-knowledge-of-javaee-standard/ JavaEE简介 JavaEE,J ...

  4. 学习Spring必学的Java基础知识(1)----反射(转)

    引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓"登高必自卑,涉远必自迩".以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系 ...

  5. 学习Spring必学的Java基础知识(1)----反射

    引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓"登高必自卑,涉远必自迩".以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系 ...

  6. Java基础知识拾遗(一)

    类型提升规则 Java定义了几个应用于表达式的类型提升规则:所有byte.short和char类型的值都被提升为int类型.如果有一个操作数是long类型,将这个表达式提升为 long 类型:如果有一 ...

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

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

  8. APK反编译之一:基础知识—APK、Dalvik字节码和smali文件

    refs: APK反编译之一:基础知识http://blog.csdn.net/lpohvbe/article/details/7981386 APK反编译之二:工具介绍http://blog.csd ...

  9. java基础知识一览(二)

    一.java基础知识 1.一个文件中只能有一个public的类,因为他的类名要求和文件名相同. 2.classpath变量可以设置其它目录下的类. 例如:类文件所在目录是:F:\Javajdk,那么没 ...

随机推荐

  1. hdu_1006 Tick and Tick(暴力模拟)

    hdu1006 标签(空格分隔): 暴力枚举 好久没有打题了,退队了有好几个月了,从心底不依赖那个人了,原来以为的爱情戏原来都只是我的独角戏.之前的我有时候好希望有个人出现,告诉自己去哪里,做什么,哪 ...

  2. Hadoop2.7.5+Hbase1.4.0完全分布式

    Hadoop2.7.5+Hbase1.4.0完全分布式一.在介绍完全分布式之前先给初学者推荐两本书:<Hbase权威指南>偏理论<Hbase实战>实战多一些 二.在安装完全分布 ...

  3. [学习OpenCV攻略][008][Canny边缘检测]

    cvGetSize(输入图片) 得到输入图片的大小 cvCanny(输入图片,输出图片,lowThresh,highThresh,aperture) 把输入图片按设定光圈值进行Canny边缘检测,然后 ...

  4. Spark性能调优之解决数据倾斜

    Spark性能调优之解决数据倾斜 数据倾斜七种解决方案 shuffle的过程最容易引起数据倾斜 1.使用Hive ETL预处理数据    • 方案适用场景:如果导致数据倾斜的是Hive表.如果该Hiv ...

  5. 织梦CMS首页调用分类信息栏目及列表方法

    不懂代码,搜索学习一晚上,都是说调用特定栏目分类信息列表的,用这个代码 {dede:arclistsg row='10' titlelen='24' orderby='pubdate' channel ...

  6. 浅谈 C/S 和 B/S 架构

    概述 在这个信息急剧膨胀的社会,我们不得不说人类正进入一个崭新的时代,那就是信息时代.信息时代的一个主要而显著的特征就是计算机网络的应用.计算机网络从最初的集中式计算,经过了Client/Server ...

  7. 月薪20k以上的高级程序员需要学习哪些技术呢?

    课程内容: 源码分析.分布式架构.微服务架构.性能优化.团队协作效率.双十一项目实战 适用对象: 1-5年或更长软件开发经验,没有工作经验但基础非常扎实,对java工作机制,常用设计思想,常用java ...

  8. 通过与Quickbuild和Mist.io的持续集成实现云管理和使用监控

    欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 这篇文章由巴拉克·梅里莫维奇撰写. 总结我自己有关Openstack的各种骚操作先告一段落.这一次我想谈谈有关监控云服务的使用情况. 我个人使用 ...

  9. 2018/1/27 每日一学 最长不降序子序列的O(n*logn)算法

    手动维护一个数组模拟即可,233-- 可以使用algorithm中的lower_bound(相当于二分) 代码如下: #include<cstdio> #include<algori ...

  10. Ios8之后, 定位的delegate不能触发的问题

    if([CLLocationManager locationServicesEnabled]){ self.locationManage = [[[CLLocationManager alloc] i ...