您的位置:首页 > 编程语言 > Java开发

thinking-in-java(20)注解入门荔枝

2017-12-27 23:39 344 查看
【1】定义注解
// 荔枝-使用注解来跟踪一个项目中的用例
// 下面定义了一个注解UseCase:该注解作用于方法,该注解在运行时发挥作用
@Target(ElementType.METHOD) // 该注解应用于什么地方
@Retention(RetentionPolicy.RUNTIME) // 该注解的应用级别,源代码-SOURCE, 类文件中-CLASS, 运行时-RUNTIME
public @interface UseCase {
public int id();

public String description() default "no description"; // no description 是默认值
} // /:~
/* 反编译后的源码:可以看到,注解就是一个接口类型,该接口的父类是 Annotation 注解接口类型,当然了,接口中的方法都是抽象方法
E:\bench-cluster\spring_in_action_eclipse\AThinkingInJava\src>javap -c chapter20.UseCase
Compiled from "UseCase.java"
public interface chapter20.UseCase extends java.lang.annotation.Annotation {
public abstract int id();

public abstract java.lang.String description();
}
*/
【2】将注解作用于方法(也可以作用于其他地方:如CONSTRUCTOR, FIELD, METHOD, LOCAL_VARIABLE, PACKAGE, PARAMETER, TYPE等)
// 荔枝-有3个方法被注解为用例
public class PasswordUtils {
// 将 UseCase 注解作用于方法
@UseCase(id = 47, description = "Passwords must contain at least one numeric")
public boolean validatePassword(String password) {
return (password.matches("\\w*\\d\\w*"));
}

@UseCase(id = 48) // description 默认为 no description
public String encryptPassword(String password) {
return new StringBuilder(password).reverse().toString();
}

@UseCase(id = 49, description = "New passwords can't equal previously used ones")
public boolean checkForNewPassword(List<String> prevPasswords, String password) {
return !prevPasswords.contains(password);
}
} // /:~
/* 反编译简要结果如下:
E:\bench-cluster\spring_in_action_eclipse\AThinkingInJava\src>javap chapter20.PasswordUtils
Compiled from "PasswordUtils.java"
public class chapter20.PasswordUtils {
public chapter20.PasswordUtils();
public boolean validatePassword(java.lang.String);
public java.lang.String encryptPassword(java.lang.String);
public boolean checkForNewPassword(java.util.List<java.lang.String>, java.lang.String);
}
*/
/* 反编译详细结果如下:
E:\bench-cluster\spring_in_action_eclipse\AThinkingInJava\src>javap -c chapter20.PasswordUtils
Compiled from "PasswordUtils.java"
public class chapter20.PasswordUtils {
public chapter20.PasswordUtils();
Code:
0: aload_0
1: invokespecial #1                  // Method java/lang/Object."<init>":()V
4: return

public boolean validatePassword(java.lang.String);
Code:
0: aload_1
1: ldc           #2                  // String \w*\d\w*
3: invokevirtual #3                  // Method java/lang/String.matches:(Ljava/lang/String;)Z
6: ireturn

public java.lang.String encryptPassword(java.lang.String);
Code:
0: new           #4                  // class java/lang/StringBuilder
3: dup
4: aload_1
5: invokespecial #5                  // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
8: invokevirtual #6                  // Method java/lang/StringBuilder.reverse:()Ljava/lang/StringBuilder;
11: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
14: areturn

public boolean checkForNewPassword(java.util.List<java.lang.String>, java.lang.String);
Code:
0: aload_1
1: aload_2
2: invokeinterface #8,  2            // InterfaceMethod java/util/List.contains:(Ljava/lang/Object;)Z
7: ifne          14
10: iconst_1
11: goto          15
14: iconst_0
15: ireturn
}
*/
【3】编写注解处理器
// 通过反射机制来编写注解处理器
public class UseCaseTracker {
// cl 是使用 UseCase注解的 Class类信息对象
public static void trackUseCases(List<Integer> useCases, Class<?> cl) {
for (Method m : cl.getDeclaredMethods()) { //  // 通过反射获取使用UseCase注解实例的对象所声明的方法列表
UseCase uc = m.getAnnotation(UseCase.class); // 方法通过反射机制(UseCase.class)获取UseCase注解实例
if (uc != null) {
System.out.println("Found Use Case:" + uc.id() + " "
+ uc.description());
useCases.remove(new Integer(uc.id()));
}
}
for (int i : useCases) {
System.out.println("Warning: Missing use case-" + i);
}
}

public static void main(String[] args) {
List<Integer> useCases = new ArrayList<Integer>();
Collections.addAll(useCases, 47, 48, 49, 50);
trackUseCases(useCases, PasswordUtils.class);
}
}
/*
Found Use Case:49 New passwords can't equal previously used ones
Found Use Case:47 Passwords must contain at least one numeric
Found Use Case:48 no description
Warning: Missing use case-50
*/
【小结】 注解就是绑定在或作用于 代码节点(如CONSTRUCTOR, FIELD, METHOD, LOCAL_VARIABLE, PACKAGE, PARAMETER, TYPE等 )的数据的类型;
有了注解的绑定,原有的代码节点可以有许多附加的信息;而且注解使得代码的复用性强和复用更加便利!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: