你是否注意到,junit 中的测试函数上方,总会有个 ‘@Test’ ? 或者在用 JavaWeb时,总会有许许多多的@?删掉或者没配置好会导致项目整个功能失常?
@Test public void test() {...}
这些都是注解在起着作用。
我们想要仿照Junit做一件这样的事情: 这样测试一个类,只要该类的方法声明了名为“Yts”的注解,那么我们就调用它,方法传入的参数在注解的声明里面。
自定义一个注解
在最开始,我们需要自定义一个注解Yts
package nicelee.annotation;
import static java.lang.annotation.ElementType.METHOD;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) //重要,不然没法在运行时读出来
@Target(METHOD)
public @interface Yts {
String uri();
}
注意到以上自定义的注解中,我们可以看到,我给该注解 注解(动词)了两个注解 - Retention和Target。我们称之为元注解。
元注解是指注解的注解。包括 @Retention @Target @Document @Inherited四种。( 例子中只有两种,是因为其他两种去的是默认值 )
- @Target 表示该注解目标,可能的 ElemenetType 参数包括:
ElemenetType.CONSTRUCTOR 构造器声明 ElemenetType.FIELD 域声明(包括 enum 实例) ElemenetType.LOCAL_VARIABLE 局部变量声明 ElemenetType.METHOD 方法声明 ElemenetType.PACKAGE 包声明 ElemenetType.PARAMETER 参数声明 ElemenetType.TYPE 类,接口(包括注解类型)或enum声明
- @Retention 表示该注解的生命周期,可选的 RetentionPolicy 参数包括
RetentionPolicy.SOURCE 注解将被编译器丢弃 RetentionPolicy.CLASS 注解在class文件中可用,但会被VM丢弃 RetentionPolicy.RUNTIME VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息
-
@Documented 指示将此注解包含在 javadoc 中
-
@Inherited 指示允许子类继承父类中的注解
自定义一个需要测试的类
这一款没啥讲究,按照想要做的来就行了
package nicelee.test;
import nicelee.annotation.Yts;
import nicelee.utils.Log;
public class ClassIncludeAnno extends Log{
@Yts(uri = "注解Yts的uri属性1 - sayHello")
public void sayHello(String name){
printf("调用SayHello方法,传参值为:%s\n",name);
}
@Yts(uri = "注解Yts的uri属性2 - sayBye")
public void sayBye(String name){
printf("调用sayBye方法,传参值为:%s\n",name);
}
public void sayHaha(String name){
printf("调用sayHaha方法,传参值为:%s\n",name);
}
}
测试
接下来没啥好说的,直接上代码:
//调用某类中的全部注解为Yts的方法
public static void main(String[] args) {
ClassIncludeAnno test = new ClassIncludeAnno();
try {
println("--------------------");
// 获取所有方法
Method[] methods = test.getClass().getDeclaredMethods();
for(Method meth : methods){
printf("当前方法名为: %s \n",meth.getName());
//该方法有无注解Yts
Yts annoYts = meth.getAnnotation(Yts.class);
//println(annoYts);
if( null != annoYts){
//通过反射调用该方法
meth.invoke(test, annoYts.uri());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
结果如下:
当前方法名为: sayHello
调用SayHello方法,传参值为:注解Yts的uri属性1 - sayHello
当前方法名为: sayBye
调用sayBye方法,传参值为:注解Yts的uri属性2 - sayBye
当前方法名为: sayHaha