java注解:如何实现和使用一个自定义注解?
2017-09-29 10:10
666 查看
java中注解在java中的应用非常广泛,如override、supperwarning等等注解,框架中的注解应用更为广泛,主流框架基本都有自己的注解体系,今天想总结和学习一下注解的相关知识,第一篇将介绍如何实现一个注解,第二篇将介绍如何应用一个注解。
1,注解有什么用? 注解的作用基本有三个:
.生成文档。这是最常见的,也是java 最早提供的注解。常用的有 @see @param @return 等
.跟踪代码依赖性,实现替代配置文件功能。比较常见的是spring 2.5 开始的基于注解配置。作用就是减少配置。现在的框架基本都使用了这种配置来减少配置文件的数量。也是
.在编译时进行格式检查。如@override 放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出。
2,实现一个最简单的注解:
上面是一个最简单的注解实现,没有定义任何的属性,其中需要注意的是@Retention(RetentionPolicy.RUNTIME)是定义注解所必须的。
@Retention是注解的注解,称为注解的元注解。括号里有一个枚举类型的值,即为注解内部定义的值。打开Retention的实现:
可以看到这里定义了一个变量value并且没有缺省值,所以不写这个value就会报错。 继续打开RetentionPolicy:
可以发现这个枚举类定义了三个值,这三个值分别代表的是我们定义的MyTarget如何保持。
还需要注意的是java的元注解一共有四个:
@Document
@Target
@Retention
@Inherited
各个的作用,读者自己查一下吧。无论如何我们实现了一个最简单的注解MyTarget,下面进行简单的测试:
运行上面的测试会打出一句话:
其中
可以判断出方法是是不是存在MyTarget的注解,能打印出这句话证明我们写的确实是一个注解。
AnnotatedElement 接口是所有程序元素(Class、Method和Constructor)的父接口,所以程序通过反射获取了某个类的AnnotatedElement对象之后,程序就可以调用该对象的如下四个个方法来访问Annotation信息:
注解处理的一个基础:
j
注解定义属性不同于java,看一下上面的Retention的定义属性方式:
这基本就是注解定义属性的方式,类似于java中定义方法,可以设置缺省值,即用注解的时候缺省值是可以不写的。
我们来看一下注解的功能之一: 为属性赋值,我们定义三个注解:
都是汽车相关的信息,中文名,英文名,销售员信息; 下面我们定义一个奔驰汽车的类,试着用注解进行赋值:
这样其实就定义和赋值完成了,我们搞一个中间类来打印一下信息:
这个类其实就是根据注解获取属性的值。
测试类:
打印信息:
看的出注解为属性赋值是成功的。利用上面的处理方式基本就可以理解了框架中使用注解如何进行DI的操作了。
java 注解的知识网络:
java技术交流群:255453635 备注:CSDN
1,注解有什么用? 注解的作用基本有三个:
.生成文档。这是最常见的,也是java 最早提供的注解。常用的有 @see @param @return 等
.跟踪代码依赖性,实现替代配置文件功能。比较常见的是spring 2.5 开始的基于注解配置。作用就是减少配置。现在的框架基本都使用了这种配置来减少配置文件的数量。也是
.在编译时进行格式检查。如@override 放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出。
2,实现一个最简单的注解:
@Retention(RetentionPolicy.RUNTIME) public @interface MyTarget { }
上面是一个最简单的注解实现,没有定义任何的属性,其中需要注意的是@Retention(RetentionPolicy.RUNTIME)是定义注解所必须的。
@Retention是注解的注解,称为注解的元注解。括号里有一个枚举类型的值,即为注解内部定义的值。打开Retention的实现:
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Retention { RetentionPolicy value(); }
可以看到这里定义了一个变量value并且没有缺省值,所以不写这个value就会报错。 继续打开RetentionPolicy:
public enum RetentionPolicy { SOURCE, CLASS, RUNTIME }
可以发现这个枚举类定义了三个值,这三个值分别代表的是我们定义的MyTarget如何保持。
用@Retention(RetentionPolicy.CLASS)修饰的注解,表示注解的信息被保留在class文件(字节码文件)中当程序编译时,但不会被虚拟机读取在运行的时候; 用@Retention(RetentionPolicy.SOURCE )修饰的注解,表示注解的信息会被编译器抛弃,不会留在class文件中,注解的信息只会留在源文件中; 用@Retention(RetentionPolicy.RUNTIME )修饰的注解,表示注解的信息被保留在class文件(字节码文件)中当程序编译时,会被虚拟机保留在运行时,
还需要注意的是java的元注解一共有四个:
@Document
@Target
@Retention
@Inherited
各个的作用,读者自己查一下吧。无论如何我们实现了一个最简单的注解MyTarget,下面进行简单的测试:
@MyTarget public void doSomething() { } @Resource public static void main(String[] args) throws Exception { Method method = MyTargetTest.class.getMethod("doSomething",null); if(method.isAnnotationPresent(MyTarget.class)) { System.out.println(method.getAnnotation(MyTarget.class)); } }
运行上面的测试会打出一句话:
@annotations.MyTarget()
其中
if(method.isAnnotationPresent(MyTarget.class))
可以判断出方法是是不是存在MyTarget的注解,能打印出这句话证明我们写的确实是一个注解。
二:注解中的属性定义
上面的内容我们实现了一个最简单的注解,但是这个注解基本是没有什么功能的,java注解的功能实现基本是通过定义属性实现的(真正实现功能有相关的处理类,处置这些属性,我们先来定义属性)。注解处理器类库(java.lang.reflect.AnnotatedElement):AnnotatedElement 接口是所有程序元素(Class、Method和Constructor)的父接口,所以程序通过反射获取了某个类的AnnotatedElement对象之后,程序就可以调用该对象的如下四个个方法来访问Annotation信息:
注解处理的一个基础:
方法1:<T extends Annotation> T getAnnotation(Class<T> annotationClass): 返回改程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null。 方法2:Annotation[] getAnnotations():返回该程序元素上存在的所有注解。 方法3:boolean is AnnotationPresent(Class<?extends Annotation> annotationClass):判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false. 方法4:Annotation[] getDeclaredAnnotations():返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注释。(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。
j
注解定义属性不同于java,看一下上面的Retention的定义属性方式:
RetentionPolicy value();
这基本就是注解定义属性的方式,类似于java中定义方法,可以设置缺省值,即用注解的时候缺省值是可以不写的。
我们来看一下注解的功能之一: 为属性赋值,我们定义三个注解:
4000 [code]@Retention(RetentionPolicy.RUNTIME) public @interface CarSalerTarget { public String salerName(); public int age() default 1; }
@Retention(RetentionPolicy.RUNTIME) public @interface CarNameTarget { String name() default ""; }
@Retention(RetentionPolicy.RUNTIME) public @interface CarSalerTarget { public String salerName(); public int age() default 1; }
都是汽车相关的信息,中文名,英文名,销售员信息; 下面我们定义一个奔驰汽车的类,试着用注解进行赋值:
public class BnechCar { @CarNameTarget(name="奔驰") private String name; @CarTypeTarget(carType= CarTypeTarget.Type.benchi) private String type; @CarSalerTarget(salerName="wpz",age=22) private String salerInfo; }
这样其实就定义和赋值完成了,我们搞一个中间类来打印一下信息:
/** * Created by wangpengzhi1 on 2017/9/29. */ public class CarInfoUtil { public static void getFruitInfo(Class<?> clazz){ Field[] fields = clazz.getDeclaredFields(); for(Field field :fields){ if(field.isAnnotationPresent(CarNameTarget.class)){ CarNameTarget name = (CarNameTarget) field.getAnnotation(CarNameTarget.class); String carColour ="汽车的中文名:"+name.name(); System.out.println(carColour); } else if(field.isAnnotationPresent(CarTypeTarget.class)){ CarTypeTarget type= (CarTypeTarget) field.getAnnotation(CarTypeTarget.class); String carType="汽车的类型:"+type.carType().toString(); System.out.println(carType); } else if(field.isAnnotationPresent(CarSalerTarget.class)){ CarSalerTarget saler= (CarSalerTarget) field.getAnnotation(CarSalerTarget.class); String salerInfo=" 销售员姓名:"+saler.salerName()+" 销售员年龄:"+ saler.age(); System.out.println(salerInfo); } } } }
这个类其实就是根据注解获取属性的值。
测试类:
@Test public void testTarget(){ CarInfoUtil.getFruitInfo(BnechCar.class); }
打印信息:
汽车的中文名:奔驰 汽车的类型:benchi 销售员姓名:wpz 销售员年龄:22
看的出注解为属性赋值是成功的。利用上面的处理方式基本就可以理解了框架中使用注解如何进行DI的操作了。
java 注解的知识网络:
java技术交流群:255453635 备注:CSDN
相关文章推荐
- Java 实现自定义异常 以及如何使用该异常
- 使用xib文件和自定义类来实现自定义View(如何利用xib封装一个View)
- 如何使用java自定义注解?demo
- java自带注解了解,自定义注解的实现,自定义注解的使用
- java web开发中,jsp使用了frameset框架,如何实现整个页面跳转,并且同一个表单中可以提交两个action
- JAVAWEB开发之Servlet3.0新特性的使用以及注解的详细使用和自定义注解的方法、动态代理的使用、利用动态代理实现细粒度的权限控制以及类加载和泛型反射
- 如何用Spring AOP和Java自定义注解实现登陆鉴权
- 如何在Android中写和使用一个自定义的java库
- 如何开发一个java开源框架-----Jvn框架之实现自定义Annotation以及拦截器(第五讲)
- 如何开发一个java开源框架-----Jvn框架之实现用注解代替配置文件
- java中,自定义注解拦截器来实现,在需要的拦截的方法上面加上一个注解@AccessRequired
- javaSE_8系列博客——Java语言的特性(四)--注解--(5)-- 如何使用自定义的注解?
- [原创]Java使用反射及自定义注解实现对象差异性比较
- 使用Spring AOP结合自定义Java注解实现动态数据源设置
- 如何使用针式PKM实现小组共享同一个知识库?
- 如何使用谷歌的自定义搜索引擎来搜寻一个ASP.NET网站
- 如何使用Css样式自定义一个DataGrid的风格
- NHibernate 如何实现使用sql自定义的函数
- Java 有几程方法可以实现一个线程?用什么关键字修饰同步?stop()和suspend()为什么不推荐使用?
- 如何使用java程序实现windows锁屏