• Java中的Annotation(2)Annotation工作原理


    上一篇文章已经介绍了如何使用JDK的三个标准Annotation,本文将介绍Annotation的原理,以及如何自定义Annotation,并利用Annotation来完成一些实际的功能。

    定义Annotation

    定义新的Annotation类型使用@interface关键字,这从一定意义上说明Annotation和接口的定义是有相似之处的。如下代码定义了一个Annotation

    	//使用DK的元数据Annotation:Retention
    	@Retention(RetentionPolicy.RUNTIME)
    	//使用JDK的元数据Annotation:Target
    	@Target(ElementType.METHOD)
    	//定义一个标记注释,不包含任何成员变量,即不可传入元数据
    public @interface Testable{
    	
    }

    使用Annotation

    定义了Annotation之后就可以在程序的任何地方使用该Annotation,对于Annotation的使用和publicfinal这样的修饰符很像,通常可以修饰类、方法、变量、接口等定义(默认情况下,Annotation用于修饰任何程序元素)。如下代码,就是使用了上面的Annotation修饰方法。

    public class MyTest {
    	//使用@Testable标记注释指定该方法是可测试的
    	@Testable
    	public static void m1(){
    		
    	}
    	public static void m2(){
    		
    	}
    	//使用@Testable标记注释指定该方法是可测试的
    	@Testable
    	public static void m3(){
    		throw new RuntimeException("Boom");
    	}
    	public static void m4(){
    		
    	}
    	//使用@Testable标记注释指定该方法是可测试的
    	@Testable
    	public static void m5(){
    		
    	}
    	public static void m6(){
    		
    	}
    	//使用@Testable标记注释指定该方法是可测试的
    	@Testable
    	public static void m7(){
    		throw new RuntimeException("Crash");
    	}
    	public static void m8(){
    		
    	}
    }
    

    提取Annotation

    一个类或者一个方法使用Annotation修饰之后需要通过反射来提取Annotation的信息。需要注意当一个Annotation类型被定义为运行时Annotation后该注释才是运行时可见的,当class文件被装载时被保存在class文件中的Annotation才会被虚拟机读取。下面代码就是将Annotation信息提取出来,根据这些信息进行相应的操作。在这里是如果某个方法被标记为可以测试的则调用这个方法。

    public class TestProcessor {
    	public static void process(String clazz)throws ClassNotFoundException{
    		int passed=0;
    		int failed=0;
    		//遍历obj对象的所有方法
    		for(Method m :Class.forName(clazz).getMethods()){
    			//如果包含@Testable标记注释
    			if(m.isAnnotationPresent(Testable.class)){
    				try{
    					//调用m方法
    					m.invoke(null);
    					//passed加1
    					passed++;
    				}catch (Exception ex) {
    					System.out.printf("方法"+m+"运行失败,异常"+ex.getCause()+"\n");
    					failed++;
    				}
    			}
    		}
    		//统计测试结果
    		System.out.println("共运行了:"+(passed+failed)+"个方法,其中:\n失败了:"+failed+",个,\n成功了:"+passed+"个!\n");
    	}
    }

    其中程序的主程序如下

    public class RunTests {
    	public static void main(String[] args) throws Exception{
    		//处理Mytest类
    		TestProcessor.process("annotation.MyTest");
    	}
    }

    运行结果如下

    工作原理

    上面仅仅是一个简单地Annotation的使用,更复杂一些的Annotation与上面的这个例子原理是一样的,只不过相应的逻辑判断以及涉及到的Annotation中的内容较为复杂而已。但是核心的部分就是借助一个操作类通过反射的方式提取Annotation信息,进行操作,简而言之:无反射,不注释(Annotation

  • 相关阅读:
    解决Failure to transfer org.apache.maven.plugins:maven-surefire-plugin:pom:2.7
    java.net.ConnectException: Connection timed out: no further information
    private static final long serialVersionUID = 1L;
    判断input[type=file]上传文件格式
    toString()和toLocaleString()有什么区别
    js时间与时间戳互相转换
    获取手机校验码倒计时
    jq判断网页是在什么浏览器打开的
    使用navigator.userAgent.toLowerCase()判断移动端类型
    jq回车触发绑定点击事件
  • 原文地址:https://www.cnblogs.com/beijiguangyong/p/2966593.html
Copyright © 2020-2023  润新知