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/