NiceLeeのBlog 用爱发电 bilibili~

Java Annotation 注解的初步使用

2018-11-02
nIceLee

阅读:


你是否注意到,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四种。( 例子中只有两种,是因为其他两种去的是默认值 )

  1. @Target 表示该注解目标,可能的 ElemenetType 参数包括:

ElemenetType.CONSTRUCTOR 构造器声明 ElemenetType.FIELD 域声明(包括 enum 实例) ElemenetType.LOCAL_VARIABLE 局部变量声明 ElemenetType.METHOD 方法声明 ElemenetType.PACKAGE 包声明 ElemenetType.PARAMETER 参数声明 ElemenetType.TYPE 类,接口(包括注解类型)或enum声明

  1. @Retention 表示该注解的生命周期,可选的 RetentionPolicy 参数包括

RetentionPolicy.SOURCE 注解将被编译器丢弃 RetentionPolicy.CLASS 注解在class文件中可用,但会被VM丢弃 RetentionPolicy.RUNTIME VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息

  1. @Documented 指示将此注解包含在 javadoc 中

  2. @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


内容
隐藏