相信用过 Junit 的朋友都知道 JUnit是Java的一个单元测试框架,在实现自动单元测试的情况下可以大大的提高开发的效率,那么我们如何自定义一个@Test注解呢?
br/>首先,我们先写一个@Test注解,如下: package annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /**
- @author Woo_home
-
@create by 2019/9/18br/>*/
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Test {br/>} @Test注解类型的声明就是它自身通过Retention和Target注解进行了注解。注解类型声明中的这种注解被称为元注解(meta-annotation)。@Retention(RetentionPolicy.RUNTIME)元注解表明,@Test注解应该在运行时保留。如果没有保留,测试工具就无法知道@Test注解。@Target(ElementType.METHOD)元注解表明,@Test注解只在方法声明中才是合法的:它不能运用到类声明。域声明或者其他程序元素上 在应用中使用@Test注解 package demo; import annotation.Test; /**
- @author Woo_home
-
@create by 2019/9/18
*/ public class TestDemo {br/>@Test public void hello(){ System.out.println("Hello World"); } } 编写测试运行类 package utils; import annotation.Test; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /**
- @author Woo_home
-
@create by 2019/9/18
*/ public class RunTests { public static void main(String[] args) throws Exception{ int tests = 0; //记录成功 int passed = 0;//记录失败 Class testClass = Class.forName("demo.TestDemo"); //反射带有@Test注解的类 for (Method m : testClass.getDeclaredMethods()) { if (m.isAnnotationPresent(Test.class)){ //Test是定义的注解类,isAnnotationPresent方法告知该工具运行哪些方法 tests++; try { m.invoke(testClass.newInstance()); //通过调用invoke反射式地运行类中所有标注了@Test的方法 passed++; }catch (InvocationTargetException wrappedExc){ Throwable exc = wrappedExc.getCause(); System.out.println(m + " failed: " + exc); }catch (Exception exc){ System.out.println("INVALID @Test: " + m); } } } System.out.printf("Passed: %d,Failed: %d%n",tests,tests-passed);br/>} } 我们运行这个类就会打印出标注有@Test注解的方法 但是标注有@Test的类只能用于没有返回值的方法,如果用了有返回值的方法就会报错,比如: package demo; import annotation.Test; /**
- @author Woo_home
-
@create by 2019/9/18
*/ public class TestDemo {br/>@Test public int test1(int i){ i = 0; return i;br/>} @Test public void hello(){ System.out.println("Hello World"); } } 案例 首先是一个空的注解类MyTest.java? : package com.iceflame.mytest; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy;br/>@Retention(RetentionPolicy.RUNTIME) public @interface MyTest {br/>} 然后是一个util类,里面的方法加上@MyTest注解 package com.iceflame.mytest; public class StringUtil {br/>@MyTest function(){ /ThinkMarkets代理申请www.kaifx.cn/broker/thinkmarkets.html} public void print() { System.out.println("print()方法执行了"); } } 最后是核心运行类,coreRunner.java(主要是用反射的思想,取出加了注解的方法并执行) package com.iceflame.mytest; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class CoreRunner { public static void main(String[] args) throws IllegalAccessException,IllegalArgumentException,InvocationTargetException,InstantiationException,ClassNotFoundException { // Class clazz=Class.forName("com.iceflame.mytest.StringUtil"); Class clazz=StringUtil.class; Method [] methods=clazz.getMethods(); for(Method m:methods) { if(m.isAnnotationPresent(MyTest.class)) { m.invoke(clazz.newInstance(),null); } } } } 需要注意的是,m.invoke(***,null) 这里的null是参数,也就是方法执行的参数,我们这里利用反射是不知道参数的,所以也能解释为什么我们用@Test的时候,加注解的方法一般都没有参数,因为方法是静态的,而参数是动态的,在运行的时候传过来,我们现在只是利用反射,反向实例化一个类,然后执行里面的某一个无参方法。br/>使用自定义注解完成@Test注解功能类似的效果 1、需求: 使用Junit是单元测试的工具,在一个类中使用@Test对程序的方法进行测试,自定义一个注解@MyTest 也将这个注解加在类的方法上,是这个方法得到执行。
-
技术分析:
【注解】 程序中有注释和注解 注释:给开发人员看. 注解:给计算机看的. 【JDK提供的注释】 @override :描述方法的重写. @SupperssWarnings :压制警告. @Deprecated ?:标记过时.br/>【自定义注解】 定义一个类:class 定义一个接口:interface 定义一个枚举:enum 定义一个注解:@interface 【自定义注解案例】 @interface MyDemo1{ } 带有属性的注解: @interface MyDemo2{ int a()default 1; String b( ); // 注解属性的类型:基本数据类型,字符串类型Sti让你过,Class,注解类型,枚举类型,以及以上类型的一维数组。 // Date 的(); Class cl(); MyDemo3 D3(); //注解 Color c(); //枚举 String[ ] arrs( ); } @MyDemo4("aaa") // ?如果属性名称为value那么使用得时候value可以省略(值出现value得属性情况下). public ?class ?Demo3{ } @interface ?MyDemo4{ String ? value; int ?a( ) default 1; } 3、步骤分析 定义一个测试类: public class Demo3{br/>@MyTest public void demo1(){ System.out.println("demo1 执行了。。。。"); } public void ? ??demo2( ){} } 定义核心运行类: 在核心运行类中有一个主函数。 获得测试类的所有方法。 获得每个方法,查看方法上是否有@MyTest注解。 br/>System.out.println("demo2执行了。。。。"); } } 定义核心运行类: 在核心运行类中有一个主函数。 获得测试类的所有方法。 获得每个方法,查看方法上是否有@MyTest注解。 如果有这个注解,让这个方法执行。 4、代码实现 通过元注解定义注解存在的阶段 定义一个注解: 核心运行类: public ? class ?Runner{ public ?static ?void ? main (String ?[ ?] ?args){ //反射:获取类得字节码对象.class Class ? ?class1=Demo3.class; //获取测试类中得所有方法: Method[ ?] ? mjethods= class.getMethods(); // ?遍历数组: for( Method ? ?method ?: ? methods){ //System.out.println( method .getName() ) ;br/>//判断方法是否有@MyTest注解:boolean ? flag =method.ispresent(MyTest.class);// System.out.println(method.getName()+"?? "+flag);??? ??? ??? if(flag){??? ??? ??? ??? // 让这个方法执行:??? ??? ??? ??? try {??? ??? ??? ??? ??? method.invoke(clazz.newInstance(),null);??? ??? ??? ??? } catch (Exception e) {??? ??? ??? ??? ??? e.printStackTrace();??? ??? ??? ??? }??? ??? ??? }??? ??? }??? }}使用注解完成JDBC工具的编写:public class JDBCUtils {??? privatestatic? String driverClass;??? privatestatic? String url;??? privatestatic? String username;??? privatestatic? String password;??? @JDBCInfo??? publicstatic Connection getConnection() throws Exception{??? ??? // 反射:??? ??? Class clazz = JDBCUtils.class;??? ??? Method method =clazz.getMethod("getConnection",null);??? ??? // 获得方法上的注解:??? ??? JDBCInfo jdbcInfo =method.getAnnotation(JDBCInfo.class);??? ??? driverClass =jdbcInfo.driverClass();??? ??? url = jdbcInfo.url();??? ??? username = jdbcInfo.username();??? ??? password = jdbcInfo.password();??? ????? ??? Class.forName(driverClass);??? ??? Connection conn =DriverManager.getConnection(url,username,password);??? ??? return conn;??? }}
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|