java 自定义注解 (custom annotation)

摘要: 最近几年写程序,越来越流行注解方式,比如 spring,hibernate 都从原来的xml配置方式转向了注解方式,原因在于写注解很方便,减少了XML 文件的配置,如果全部用XML 配置,一个大型的应用,怎么也得有成百上千的XML文件。那么怎么自定义类似于spring 的注解方式呢。

最近几年写程序,越来越流行注解方式,比如 spring,hibernate 都从原来的xml配置方式转向了注解方式,原因在于写注解很方便,减少了XML 文件的配置,如果全部用XML 配置,一个大型的应用,怎么也得有成百上千的XML文件。那么怎么自定义类似于spring 的注解方式呢。

java 提供了@interface 来自定义注解的申明
在定义了这个注解之后,可以将这个注解 加到方法上面,比如 @Test(enable = false) .

package com.yihaomen.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) //只能在方法上应用.
public @interface Test { 
	//是否开启
	public boolean enabled() default true; 
}


另外定义个类级别的注解:@TesterInfo
package com.yihaomen.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) //类级别
public @interface TesterInfo {
 
	public enum Priority {
	   LOW, MEDIUM, HIGH
	}
 
	Priority priority() default Priority.MEDIUM;
 
	String[] tags() default "";
 
	String createdBy() default "yihaomen";
 
	String lastModified() default "11/01/2014";
 
}


写一个单元测试,利用自定义的注解 @Test, @TesterInfo
package com.yihaomen.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 = "yihaomen.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.
	  }
	}
 
}


利用java 反射 读取注解并做相关的处理
package com.yihaomen.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 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);
 
	}
}


运行 RunTest 类的Main 方法,就可以得到结果了。
Testing...
 
Priority :HIGH
CreatedBy :yihaomen.com
Tags :sales, test
LastModified :11/01/2014
 
1 - Test 'testA' - failed: java.lang.RuntimeException: This test always failed 
2 - Test 'testC' - passed 
3 - Test 'testB' - ignored
 
Result : Total : 3, Passed: 1, Failed 1, Ignore 1


当然,如果你想更好的处理类似这样的功能,可以采用spring aop + AspectJ 方式 来完成,有空我将继续测试.

上一篇: java 获取HttpRequest Header 的几种方法
下一篇: Hibernate 使用 C3P0 连接池
 评论 ( What Do You Think )
名称
邮箱
网址
评论
验证
   
 

 


  • 微信公众号

  • 我的微信

站点声明:

1、一号门博客CMS,由Python, MySQL, Nginx, Wsgi 强力驱动

2、部分文章或者资源来源于互联网, 有时候很难判断是否侵权, 若有侵权, 请联系邮箱:summer@yihaomen.com, 同时欢迎大家注册用户,主动发布无版权争议的 文章/资源.

3、鄂ICP备14001754号-3, 鄂公网安备 42280202422812号