java 自定义注解 (custom annotation)

最近几年写程序,越来越流行注解方式,比如 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<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) {
              ZgbE'EZgbint(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 方式 来完成,有空我将继续测试.

除非申明,文章均为一号门原创,转载请注明本文地址,谢谢!
文章来自: 本站原创
引用通告: 查看所有引用 | 我要引用此文章
Tags: annotation
相关日志:
评论: 0 | 引用: 0 | 查看次数: -
发表评论
昵 称:
密 码: 游客发言不需要密码.
内 容:
验证码: 验证码
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.