引言

上一篇文章,我们学习了java中注解的创建,知道了注解元素和元注解的概念。这篇文章,我们来学习如何获取在运行时注解的信息。

运行时获取注解信息

运行时获取注解信息需要我们的注解的@Retention取值为RUNTIME,也就是必须被虚拟机保留。怎么获取呢,java提供了反射的API来帮助我们获取,看下面的例子:

  1. @Target(ElementType.METHOD)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. public @interface UseCase {
  4. int id();
  5. String description() default "no description";
  6. }

注意@Retention的取值,必须是RUNTIME。
然后添加几个使用该注解的方法:

  1. public class PasswordUtils {
  2. @UseCase(id = 47, description = "Password must contain at least one numeric")
  3. public boolean validatePassword(String password){
  4. return password.matches("\\w*\\d\\w*");
  5. }
  6. @UseCase(id = 48)
  7. public String encryptPassword(String password){
  8. return new StringBuilder(password).reverse().toString();
  9. }
  10. @UseCase(id = 49,description = "New passwords can't equal previously used ones")
  11. public boolean checkForNewPassword(List<String> prevPasswords,String password){
  12. return !prevPasswords.contains(password);
  13. }
  14. }

编写注解处理器:

  1. public class UseCaseTracker {
  2. public static void trackUseCases(Class<?> cl){
  3. for (Method declaredMethod : cl.getDeclaredMethods()) {
  4. UseCase uc = declaredMethod.getAnnotation(UseCase.class);
  5. if(null != uc){
  6. System.out.println(uc.id()+ " " +uc.description());
  7. }
  8. }
  9. }
  10. public static void main(String[] args) {
  11. trackUseCases(PasswordUtils.class);
  12. }
  13. }

在这个处理器里面,我们通过反射获取了PasswordUtils的所有method,然后调用每个method的getAnnotation方法获取该方法上的注解,有了注解之后,我们就能拿到注解元素的值了。输出如下:

  1. 47 Password must contain at least one numeric
  2. 48 no description
  3. 49 New passwords can't equal previously used ones

所以说,想要在运行时获取注解的信息,我们需要通过java反射提供的能力,不光是method,Class、Field、Constructor、Package等,只要是ElementType,就有获取注解的API,这些我们不在去详细介绍,此外,注解的@Retention的取值必须为RetentionPolicy.RUNTIME。
当@Retention注解的取值不是RUNTIME的时候,就不能通过反射来获取注解信息了,但是可以使用javac来处理注解,这里不再详细展开。

小结

这篇文章,我们学习了怎样在运行时获取注解的信息,并通过这些信息实现一些功能。很多框架例如Spring、JUnit,都利用这种获取注解的方法在框架中发挥了很大的功能同时保证了框架的短小精致,读者有兴趣可以去研究一下这些框架的源码。