最代码官方的gravatar头像
最代码官方 2014-11-18 17:27:43

java自定义注解实例

In this tutorial, we will show you how to create two custom annotations – @Test and @TestInfo, to simulate a simple unit test framework.

在这篇教程中,我们将示范如何新建两个自定义的标注: @Test和@TestInfo,并模拟一个简单的单元测试框架。

P.S This unit test example is inspired by this official Java annotation article.

这个单元测试例子的灵感来自于oracle官方文章。

1. @Test Annotation

This @interface tells Java this is a custom annotation. Later, you can annotate it on method level like this @Test(enable=false).

这个@interface标识java程序,这是一份自定义标注。之后,你可以在方法级别上标注它就像这样@Test(enable=false)

Test.java

package com.mkyong.test.core;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) //can use in method only.
public @interface Test {
 
	//should ignore this test?
	public boolean enabled() default true;
 
}

Note
Method declarations must not have any parameters or a throws clause. Return types are restricted to primitives, String, Class, enums, annotations, and arrays of the preceding types.

注意

方法申明必须不能带有任何参数或throws片段,返回类型限制为基本类型,字符串String,类Class,枚举eunms,标注和这些类型的数组

2. @TesterInfo Annotation

This @TesterInfo is applied on class level, store the tester details. This shows the different use of return types – enum, array and string.

@TesterInfo应用到类级别,保存tester的详情。这个类演示返回不同的类型:enum, array and string

TesterInfo.java

package com.mkyong.test.core;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) //on class level
public @interface TesterInfo {
 
	public enum Priority {
	   LOW, MEDIUM, HIGH
	}
 
	Priority priority() default Priority.MEDIUM;
 
	String[] tags() default "";
 
	String createdBy() default "Mkyong";
 
	String lastModified() default "03/01/2014";
 
}

3. Unit Test Example

Create a simple unit test example, and annotated with the new custom annotations – @Test and @TesterInfo.

新建一个简单的单元测试实例,并且通过新建的标注来标注:@Test and @TesterInfo

TestExample.java

package com.mkyong.test;
 
import com.mkyong.test.core.Test;
import com.mkyong.test.core.TesterInfo;
import com.mkyong.test.core.TesterInfo.Priority;
 
@TesterInfo(
	priority = Priority.HIGH, 
	createdBy = "mkyong.com",  
	tags = {"sales","test" }
)
public class TestExample {
 
	@Test
	void testA() {
	  if (true)
		throw new RuntimeException("This test always failed");
	}
 
	@Test(enabled = false)
	void testB() {
	  if (false)
		throw new RuntimeException("This test always passed");
	}
 
	@Test(enabled = true)
	void testC() {
	  if (10 > 1) {
		// do nothing, this test always passed.
	  }
	}
 
}

4. Java reflection – Read the Annotation

Below example show you how to use Java reflection APIs to read and process the custom annotations.

下面的例子演示如何通过java反射来读取和处理自定义标注。

RunTest.java

package com.mkyong.test;
 
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
 
import com.mkyong.test.core.Test;
import com.mkyong.test.core.TesterInfo;
 
public class RunTest {
 
  public static void main(String[] args) throws Exception {
 
	System.out.println("Testing...");
 
	int passed = 0, failed = 0, count = 0, ignore = 0;
 
	Class<TestExample> obj = TestExample.class;
 
	// Process @TesterInfo
	if (obj.isAnnotationPresent(TesterInfo.class)) {
 
		Annotation annotation = obj.getAnnotation(TesterInfo.class);
		TesterInfo testerInfo = (TesterInfo) annotation;
 
		System.out.printf("%nPriority :%s", testerInfo.priority());
		System.out.printf("%nCreatedBy :%s", testerInfo.createdBy());
		System.out.printf("%nTags :");
 
		int tagLength = testerInfo.tags().length;
		for (String tag : testerInfo.tags()) {
			if (tagLength > 1) {
				System.out.print(tag + ", ");
			} else {
				System.out.print(tag);
			}
			tagLength--;
		}
 
		System.out.printf("%nLastModified :%s%n%n", testerInfo.lastModified());
 
	}
 
	// Process @Test
	for (Method method : obj.getDeclaredMethods()) {
 
		// if method is annotated with @Test
		if (method.isAnnotationPresent(Test.class)) {
 
			Annotation annotation = method.getAnnotation(Test.class);
			Test test = (Test) annotation;
 
			// if enabled = true (default)
			if (test.enabled()) {
 
			  try {
				method.invoke(obj.newInstance());
				System.out.printf("%s - Test '%s' - passed %n", ++count, method.getName());
				passed++;
			  } catch (Throwable ex) {
				System.out.printf("%s - Test '%s' - failed: %s %n", ++count, method.getName(), ex.getCause());
				failed++;
			  }
 
			} else {
				System.out.printf("%s - Test '%s' - ignored%n", ++count, method.getName());
				ignore++;
			}
 
		}
 
	}
	System.out.printf("%nResult : Total : %d, Passed: %d, Failed %d, Ignore %d%n", count, passed, failed, ignore);
 
	}
}

Output

Testing...
 
Priority :HIGH
CreatedBy :mkyong.com
Tags :sales, <strong>test</strong>
LastModified :03<strong>/</strong>01<strong>/</strong><span style="color:#000000">2014</span>
 
<span style="color:#000000">1</span> - Test <span style="color:#ff0000">'testA'</span> - failed: java.lang.RuntimeException: This <strong>test</strong> always failed 
<span style="color:#000000">2</span> - Test <span style="color:#ff0000">'testC'</span> - passed 
<span style="color:#000000">3</span> - Test <span style="color:#ff0000">'testB'</span> - ignored
 
Result : Total : <span style="color:#000000">3</span>, Passed: <span style="color:#000000">1</span>, Failed <span style="color:#000000">1</span>, Ignore <span style="color:#000000">1</span>

原文:http://www.mkyong.com/java/java-custom-annotations-example/


打赏

顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友