如约所致~ Annotation详细介绍

转自:http://snkcxy.iteye.com/blog/1821512

 

1.annotation类型(叫法有很多种,官方API这样定义:Annotation Types)

  1. @Documented:被这个类型标识(修饰)的annotation  将会被javadoc或其他文档工具提取
  2. @Inherited:表示具有继承性,被这个类型标识(修饰)的annotation 它的子类将会自动被它标识(修饰)
  3. @Retention:annotation将被保留多长时间
  4. @Target:指定被标识(修饰)的annotation 能用于修饰程序的哪些部分(类、方法、成员变量等)

2.两个枚举类ElementType和RetentionPolicy

  1. ElementType:枚举了@Target类型的value值
    ElementType.FIELD:用于修饰成员变量
    ElementType.METHOD:用于修饰方法
    当然不止这些,更加详细的可查api或者ide下自己试试
  2. RetentionPolicy:枚举了@Retention的value值
    RetentionPolicy.RUNTIME:直到运行时候都会保留的annotation
    RetentionPolicy.CLASS:记录在class文件中,但是运行时不会被保留
    RetentionPolicy.SOURCE:保留在源码中,会被编译器丢弃

3.如何自己定义一个annotation(具体见例子中的注释)

  1. 使用@interface关键字,和定义类,定义接口类似
    @interface MyAnnotation{} 这样一个最简单的annotation就定义好了。
  2. 定义元数据,暂时可以理解为成员变量
  3. 编写一个annotation处理器(通过反射获取annotation信息或者通过实现接口,继承抽象类来完成)

4.例子1简单讲解

  1. 我们要做什么?
    原始的Aclass 没有日志,我们现在要给一些方法加上日志的功能(有点AOP思想)
  2. 目录结构:
    a.Aclass:一个演示目标类,里面提供了4个方法,有2个打上了@CxyLog标记,当使用annotation处理器去处理的时候会看到打上标记的会输出日志语句。
    b.(不带元数据的)@CxyLog:加上这个标记的就自动加上打印日志功能
     c.CxyLogAp:annotation处理器,这里主要处理@CxyLog
  3. 说明:
    1.一个很简单的例子,意在演示:如何创建一个annotation和annotation处理器,并让其工作起来
    2.本例借助的是AOP的概念,但是绝对不是实现AOP。所以程序运行时并不是一个一个方法去调用。
    3.实现AOP需要涉及接口、反射、动态代理、aop概念等等知识,这里只是单纯的做annotation的介绍。

5.例子2简单讲解

  1. 我们要做什么?
    根据权限动态装配对应的类(bo)
  2. 目录结构
    a.CxyAction:测试目标类,提供了两个不同权限的方法
    b.CxyBo:一个接口为了演示动态装配而生
    c.CxyCommonBo:普通权限的bo,实现CxyBo接口
    d.CxyAdvancedBo:高级权限的bo,实现CxyBo接口
    e.@CxyAuthority:标记方法的权限及对应权限的实现类
    f.CxyAuthorityAp:@CxyAuthority的处理器
  3. 说明:
    1.本例演示了一个带元数据的annotation,并根据元数据信息(authority和boName)来动态装配bo。
    2.本例仅仅是演示annotation用法,实际工作中并不会这样去控制权限或者装配bo。
    3.authority和boName的存在貌似有些重复,那是因为这个例子里authority和boName是一对一的关系,如果是多对多的关系,这两个元信息就不会觉得是重复的了。

6.总结一下 看看我们干了什么?

  • 其实就是给程序的某个部位(类、成员变量、方法等)打了一个标记,这个标记其实没什么大不了(不复杂不深奥顶多就是一个程序注释)
  • 但是如果你自己写了一个annotation处理器去处理这个标记的话,那么它能为你做到很多很多。

说明:本例只是阐述annotation的详细用法,我会尽快出一个较为有意义的实例应用文章。

 

例一:

Java代码 复制代码  收藏代码
  1. package com.cxy.annotation;   
  2.   
  3. import java.lang.annotation.ElementType;   
  4. import java.lang.annotation.Retention;   
  5. import java.lang.annotation.RetentionPolicy;   
  6. import java.lang.annotation.Target;   
  7. import java.lang.reflect.Method;   
  8.   
  9. /**  
  10.  * @author cxy  
  11.  */  
  12. public class AnnotationDetailTest   
  13. {   
  14.     public static void main(String[] args) throws Exception   
  15.     {   
  16.         CxyLogAp.Processor(Aclass.class);   
  17.     }   
  18. }   
  19.   
  20. /**  
  21.  * 一个测试用的类,这个类的method1和method3被@CxyLog标记  
  22.  */  
  23. class Aclass   
  24. {   
  25.     @CxyLog  
  26.     public static void method1(){System.out.println("method1执行");}   
  27.     public static void method2(){System.out.println("method2执行");}   
  28.     @CxyLog  
  29.     public static void method3(){System.out.println("method3执行");}   
  30.     public static void method4(){System.out.println("method4执行");}   
  31. }   
  32.   
  33. /**  
  34.  * 一个简单的annotation,打上这个标记的我们就给这个方法加入日志打印功能  
  35.  * 1.@Retention(RetentionPolicy.RUNTIME) 解释:保留注释到程序运行  
  36.  * 2.@Target(ElementType.METHOD) 解释:这个annotation是标记在方法上的  
  37.  */  
  38. @Retention(RetentionPolicy.RUNTIME)    
  39. @Target(ElementType.METHOD)    
  40. @interface CxyLog{}    
  41.   
  42.   
  43. /**这个类是@CxyLog的annotation处理器  
  44.  */  
  45. class CxyLogAp   
  46. {   
  47.     //处理器 处理@CxyLog标记   
  48.     public static void Processor(Class clz) throws Exception   
  49.     {   
  50.         for(Method m:clz.getMethods())   
  51.         {   
  52.             //如果当前访问的方法打上了@CxyLog标识,那么就加入打印语句   
  53.             if(m.isAnnotationPresent(CxyLog.class))   
  54.             {   
  55.                 m.invoke(null);   
  56.                 System.out.println("日志:"+clz+"."+m.getName()+"执行!");   
  57.             }else  
  58.             {   
  59.                 //因为他会执行所有的方法,包括父类的很多方法,所以这里我们限定一下只做我们定义的method开头的方法   
  60.                 if(m.getName().contains("method"))   
  61.                 {   
  62.                     m.invoke(null);   
  63.                 }   
  64.             }   
  65.         }   
  66.     }   
  67. }  
package com.cxy.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;

/**
 * @author cxy
 */
public class AnnotationDetailTest
{
	public static void main(String[] args) throws Exception
	{
		CxyLogAp.Processor(Aclass.class);
	}
}

/**
 * 一个测试用的类,这个类的method1和method3被@CxyLog标记
 */
class Aclass
{
	@CxyLog
	public static void method1(){System.out.println("method1执行");}
	public static void method2(){System.out.println("method2执行");}
	@CxyLog
	public static void method3(){System.out.println("method3执行");}
	public static void method4(){System.out.println("method4执行");}
}

/**
 * 一个简单的annotation,打上这个标记的我们就给这个方法加入日志打印功能
 * 1.@Retention(RetentionPolicy.RUNTIME) 解释:保留注释到程序运行
 * 2.@Target(ElementType.METHOD) 解释:这个annotation是标记在方法上的
 */
@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.METHOD) 
@interface CxyLog{} 


/**这个类是@CxyLog的annotation处理器
 */
class CxyLogAp
{
	//处理器 处理@CxyLog标记
	public static void Processor(Class clz) throws Exception
	{
		for(Method m:clz.getMethods())
		{
			//如果当前访问的方法打上了@CxyLog标识,那么就加入打印语句
			if(m.isAnnotationPresent(CxyLog.class))
			{
				m.invoke(null);
				System.out.println("日志:"+clz+"."+m.getName()+"执行!");
			}else
			{
				//因为他会执行所有的方法,包括父类的很多方法,所以这里我们限定一下只做我们定义的method开头的方法
				if(m.getName().contains("method"))
				{
					m.invoke(null);
				}
			}
		}
	}
}

 

结果图:


    
 

例二:

Java代码 复制代码  收藏代码
  1. package com.cxy.annotation;   
  2.   
  3. import java.lang.annotation.Annotation;   
  4. import java.lang.annotation.ElementType;   
  5. import java.lang.annotation.Retention;   
  6. import java.lang.annotation.RetentionPolicy;   
  7. import java.lang.annotation.Target;   
  8. import java.lang.reflect.Method;   
  9.   
  10. /**  
  11.  * @author cxy  
  12.  */  
  13. public class AnnotationDetailTest1   
  14. {   
  15.     public static void main(String[] args) throws Exception   
  16.     {   
  17.         CxyAction.commonAuthoritymethod();   
  18.         CxyAction.advanceAuthoritymethod();   
  19.         System.out.println("=============================");   
  20.         //以下面的两种方式执行这两个方法   
  21.         CxyAuthorityAp.Processor(CxyAction.class"commonAuthoritymethod");   
  22.         System.out.println("------------------------------");   
  23.         CxyAuthorityAp.Processor(CxyAction.class"advanceAuthoritymethod");   
  24.     }   
  25. }   
  26.   
  27. /** 测试目标类,提供了两个不同权限的方法  
  28.  */  
  29. class CxyAction   
  30. {   
  31.     public static CxyBo bo=new CxyCommonBo(); //初始时候装配的是普通权限的bo   
  32.        
  33.     //普通权限就能访问的方法   
  34.     @CxyAuthority(authority="c",boName=CxyCommonBo.class)   
  35.     public static void commonAuthoritymethod()   
  36.     {   
  37.         bo.doSomething();   
  38.     }    
  39.        
  40.     //高级权限能访问的方法    
  41.     @CxyAuthority(authority="a",boName=CxyAdvancedBo.class)   
  42.     public static void advanceAuthoritymethod()   
  43.     {   
  44.         bo.doSomething();   
  45.     }    
  46. }   
  47.   
  48. /** 一个接口为了演示动态装配而生  
  49.  */  
  50. interface CxyBo   
  51. {   
  52.     public void doSomething();   
  53. }   
  54.   
  55. /** 普通权限的bo  
  56.  */  
  57. class CxyCommonBo implements CxyBo   
  58. {   
  59.     //普通业务逻辑   
  60.     @Override  
  61.     public void doSomething()   
  62.     {   
  63.         System.out.println("执行:普通权限处理方法");   
  64.     }   
  65. }   
  66.   
  67. /** 高级权限的bo  
  68.  */  
  69. class CxyAdvancedBo implements CxyBo   
  70. {   
  71.     //高级业务逻辑   
  72.     @Override  
  73.     public void doSomething()   
  74.     {   
  75.         System.out.println("执行:高级权限处理方法");   
  76.     }   
  77. }   
  78.   
  79. //权限annotation,根据这个标记的authority值来判断装配哪个业务逻辑类   
  80. @Retention(RetentionPolicy.RUNTIME)    
  81. @Target(ElementType.METHOD)    
  82. @interface CxyAuthority   
  83. {   
  84.     String authority(); //代表权限   
  85.     Class boName(); //代表这个权限用什么bo去处理   
  86. }   
  87.   
  88. /**这个类是@CxyAuthority的annotation处理器  
  89.  */  
  90. class CxyAuthorityAp   
  91. {   
  92.     //处理器 处理@CxyAuthority标记   
  93.     public static void Processor(Class clz,String methodName) throws Exception   
  94.     {   
  95.         Method m=clz.getMethod(methodName, null); //获得指定类的指定方法   
  96.         Annotation[] aArray=m.getAnnotations(); //获得方法所有的annotation   
  97.         for(Annotation one:aArray)   
  98.         {   
  99.             if(one instanceof CxyAuthority)   
  100.             {   
  101.                 CxyBo tempBo=(CxyBo) ((CxyAuthority)one).boName().newInstance();   
  102.                 if("c".equals(((CxyAuthority)one).authority()))   
  103.                 {   
  104.                     System.out.println("装配信息:普通权限bo装配成功");   
  105.                     //这里还可以做一些权限控制的操作   
  106.                 }else if("a".equals(((CxyAuthority)one).authority()))   
  107.                 {   
  108.                     System.out.println("装配信息:高级权限bo装配成功");   
  109.                     //这里还可以做一些权限控制的操作   
  110.                 }   
  111.                 tempBo.doSomething();   
  112.             }   
  113.         }   
  114.     }   
  115. }  
package com.cxy.annotation;

import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;

/**
 * @author cxy
 */
public class AnnotationDetailTest1
{
	public static void main(String[] args) throws Exception
	{
		CxyAction.commonAuthoritymethod();
		CxyAction.advanceAuthoritymethod();
		System.out.println("=============================");
		//以下面的两种方式执行这两个方法
		CxyAuthorityAp.Processor(CxyAction.class, "commonAuthoritymethod");
		System.out.println("------------------------------");
		CxyAuthorityAp.Processor(CxyAction.class, "advanceAuthoritymethod");
	}
}

/** 测试目标类,提供了两个不同权限的方法
 */
class CxyAction
{
	public static CxyBo bo=new CxyCommonBo(); //初始时候装配的是普通权限的bo
	
	//普通权限就能访问的方法
	@CxyAuthority(authority="c",boName=CxyCommonBo.class)
	public static void commonAuthoritymethod()
	{
		bo.doSomething();
	} 
	
	//高级权限能访问的方法 
	@CxyAuthority(authority="a",boName=CxyAdvancedBo.class)
	public static void advanceAuthoritymethod()
	{
		bo.doSomething();
	} 
}

/** 一个接口为了演示动态装配而生
 */
interface CxyBo
{
	public void doSomething();
}

/** 普通权限的bo
 */
class CxyCommonBo implements CxyBo
{
	//普通业务逻辑
	@Override
	public void doSomething()
	{
		System.out.println("执行:普通权限处理方法");
	}
}

/** 高级权限的bo
 */
class CxyAdvancedBo implements CxyBo
{
	//高级业务逻辑
	@Override
	public void doSomething()
	{
		System.out.println("执行:高级权限处理方法");
	}
}

//权限annotation,根据这个标记的authority值来判断装配哪个业务逻辑类
@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.METHOD) 
@interface CxyAuthority
{
	String authority(); //代表权限
	Class boName(); //代表这个权限用什么bo去处理
}

/**这个类是@CxyAuthority的annotation处理器
 */
class CxyAuthorityAp
{
	//处理器 处理@CxyAuthority标记
	public static void Processor(Class clz,String methodName) throws Exception
	{
		Method m=clz.getMethod(methodName, null); //获得指定类的指定方法
		Annotation[] aArray=m.getAnnotations(); //获得方法所有的annotation
		for(Annotation one:aArray)
		{
			if(one instanceof CxyAuthority)
			{
				CxyBo tempBo=(CxyBo) ((CxyAuthority)one).boName().newInstance();
				if("c".equals(((CxyAuthority)one).authority()))
				{
					System.out.println("装配信息:普通权限bo装配成功");
					//这里还可以做一些权限控制的操作
				}else if("a".equals(((CxyAuthority)one).authority()))
				{
					System.out.println("装配信息:高级权限bo装配成功");
					//这里还可以做一些权限控制的操作
				}
				tempBo.doSomething();
			}
		}
	}
}

 结果图:


    
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值