Java自定义注解和解析注解

在SpringBoot中,注解太多了,但是不知道注解是怎么工作的,所以我就开始研究注解的开发和使用,本文章就从java注解开始学习。

在java中,内置了3种注解(元数据)分别是@Override,@Deprecated@SuppressWarnings。当然只有这3中是远远不够的所以还定义了4种注解,专门用来创建其他注解的,就是自定义注解,我们接下来要学习的是如何自定义自己的注解和使用注解。

一.准备知识:

  1. 四种注解(元注解): 4种注解(元注解):
    Java口前只内置了三种标准注解(前面介绍过),以及四种元注解。元注解专职负责注解其他的注解

注解 说明
@Target 用来定义你的注解是用在什么地方,可以多选,如类,方法还是字段。ElementType参数包括:CONSTRUCTOR:构造器的声明,FIELD:域声明,LOCAL_VARIABLE:局部变量声明,METHOD:方法声明,PACKAGE:包声明,PARAMETER:参数声明,TYPE:类,接口,emum声明
@Retention 用来定义在什么时候保存这注解,参数有:SOURCE:注解被编译器去掉,CLASS:注解在class文件可以用,但是被VM去掉,REUNTIME:在VM种也能用,可以用反射机制获取信息
@Documented 将注解包含在Javadoc种
@Inherited 允许子类继承父类中的注解

2.Class类中getMethods() 与getDeclaredMethods() 方法的区别
public Method[] getMethods()返回某个类的所有公用(public)方法包括其继承类的公用方法,当然也包括它所实现接口的方法。
public Method[] getDeclaredMethods()对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。当然也包括它所实现接口的方法。
3.getDeclaredField和getField区别
getFields():获得某个类的所有的公共(public)的字段,包括父类中的字段。
getDeclaredFields():获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段。
4.getAnnotation()方法
java.lang.Package.getAnnotation(Class annotationClass) 方法返回该元素的指定类型的注释,如果是这样的注释,否则返回null。
5.isAnnotationPresent()
java.lang.Package.isAnnotationPresent(Class annotationClass) 方法返回true,如果指定类型的注释存在于此元素上,否则返回false。
二.例子
先自定义注解:

  1. /**
  2. * 水果名称注解
  3. * @author peida
  4. *
  5. */
  6. @Target(ElementType.FIELD)
  7. @Retention(RetentionPolicy.RUNTIME)
  8. @Documented
  9. public @interface FruitName {
  10. String value() default "";
  11. }
  12. /**
  13. * 水果颜色注解
  14. * @author peida
  15. *
  16. */
  17. @Target(ElementType.FIELD)
  18. @Retention(RetentionPolicy.RUNTIME)
  19. @Documented
  20. public @interface FruitColor {
  21. /**
  22. * 颜色枚举
  23. * @author peida
  24. *
  25. */
  26. public enum Color{ BULE,RED,GREEN};
  27. /**
  28. * 颜色属性
  29. * @return
  30. */
  31. Color fruitColor() default Color.GREEN;
  32. }
  33. /**
  34. * 水果供应者注解
  35. * @author peida
  36. *
  37. */
  38. @Target(ElementType.FIELD)
  39. @Retention(RetentionPolicy.RUNTIME)
  40. @Documented
  41. public @interface FruitProvider {
  42. /**
  43. * 供应商编号
  44. * @return
  45. */
  46. public int id() default -1;
  47. /**
  48. * 供应商名称
  49. * @return
  50. */
  51. public String name() default "";
  52. /**
  53. * 供应商地址
  54. * @return
  55. */
  56. public String address() default "";
  57. }

如果没有用来读取注解的方法和工作,那么注解也就不会比注释更有用处了。使用注解的过程中,很重要的一部分就是创建于使用注解处理器。Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处理器

自定义注解处理器

  1. public class FruitInfoUtil {
  2. public static void getFruitInfo(Class clazz){
  3. String strFruitName=" 水果名称:";
  4. String strFruitColor=" 水果颜色:";
  5. String strFruitProvicer="供应商信息:";
  6. Field[] fields = clazz.getDeclaredFields();
  7. for(Field field :fields){
  8. if(field.isAnnotationPresent(FruitName.class)){
  9. FruitName fruitName = (FruitName) field.getAnnotation(FruitName.class);
  10. strFruitName=strFruitName+fruitName.value();
  11. System.out.println(strFruitName);
  12. }
  13. else if(field.isAnnotationPresent(FruitColor.class)){
  14. FruitColor fruitColor= (FruitColor) field.getAnnotation(FruitColor.class);
  15. strFruitColor=strFruitColor+fruitColor.fruitColor().toString();
  16. System.out.println(strFruitColor);
  17. }
  18. else if(field.isAnnotationPresent(FruitProvider.class)){
  19. FruitProvider fruitProvider= (FruitProvider) field.getAnnotation(FruitProvider.class);
  20. strFruitProvicer=" 供应商编号:"+fruitProvider.id()+" 供应商名称:"+fruitProvider.name()+" 供应商地址:"+fruitProvider.address();
  21. System.out.println(strFruitProvicer);
  22. }
  23. }
  24. }
  25. }

测试

  1. public class FruitRun {
  2. /**
  3. * @param args
  4. */
  5. public static void main(String[] args) {
  6. FruitInfoUtil.getFruitInfo(Apple.class);
  7. }
  8. }
  9. ====================================
  10. 水果名称:Apple
  11. 水果颜色:RED
  12. 供应商编号:1 供应商名称:陕西红富士集团 供应商地址:陕西省西安市延安路89号红富士大厦

三.注意:
默认值限制:
编译器对元素的默认值有些过分挑剔。首先,元素不能有不确定的值。也就是说.,元素必须要么具有默认值,要么在使用注解时提供元素的值。 其次,对于非基本类型的元素,无论是在源代码中声明时,或是在注解接口中定义默认值时,都不能以null作为其值。这个约束使得处理器很难表现一个元素的存在或缺失的状态,因为在每个注解的声明中,所有的元素都存在,并且都具有相应的值。为了绕开这个约束,我们只能自己定义一些特殊的值,例如空字符串或负数,以此表示某个元素不存在.