开发中自定义annotation的场景不太多,但是很多框架的源码里都用到了自定义annotation,不了解的话就看不懂了,所以也简单地学习一下
试了一下,比较简单,以下通过一个例子来说明
首先是annotation本身的定义
1 2 3 4 5 6 7 8 9 10 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ValueBind { public FieldType type(); public String value(); }
这里用了一个枚举
1 2 3 4 5 public enum FieldType { STRING, INT }
下面是用到了该标签的类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 public class Student { private String id; private String name; private int age; @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("id: " + this.getId() + "\n"); sb.append("name: " + this.getName() + "\n"); sb.append("age: " + this.getAge() + "\n"); return sb.toString(); } public String getId() { return id; } @ValueBind(type = FieldType.STRING, value = "123") public void setId(String id) { this.id = id; } public String getName() { return name; } @ValueBind(type = FieldType.STRING, value = "kyfxbl") public void setName(String name) { this.name = name; } public int getAge() { return age; } @ValueBind(type = FieldType.INT, value = "29") public void setAge(int age) { this.age = age; } }
最后是执行的代码,可以看到效果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public class Main { public static void main(String[] args) throws Exception { Student student = new Student(); System.out.println(student.toString()); Method[] methodArray = student.getClass().getDeclaredMethods(); for (Method method : methodArray) { if (method.isAnnotationPresent(ValueBind.class)) { ValueBind annotation = method.getAnnotation(ValueBind.class); FieldType type = annotation.type(); String value = annotation.value(); if (FieldType.INT.equals(type)) { method.invoke(student, new Integer(value)); } else { method.invoke(student, value); } } } System.out.println(student.toString()); } }
我总的感觉,注解本身干不了啥,只能起到一个类型标识的作用(正如其命名annotation一样),然后代码里可以根据注解的类型,再进行需要的处理,相当于annotation起到的是类型标记的作用
不过在annotation里可以定义一些字段,这样可以传递参数过去
另外,注解也是可以“继承”的,比如说,在spring框架中,@Controller、@Service、@Repository,都认为是@Component
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Repository { /** * The value may indicate a suggestion for a logical component name, * to be turned into a Spring bean in case of an autodetected component. * @return the suggested component name, if any */ String value() default ""; }