Spring自定义注解

时间:2022-04-18 20:37:17

Java注解:附在代码中的一些元信息,用于在编译、运行时起到说明、配置的功能。


一、元注解

java提供了4种元注解用于注解其他注解,所有的注解都是基于这四种注解来定义的。


@Target注解:用于描述注解的使用范围,超出范围时编译失败。

  取值类型(ElementType):

    1.CONSTRUCTOR:用于描述构造器

    2.FIELD:用于描述域(成员变量)

    3.LOCAL_VARIABLE:用于描述局部变量

    4.METHOD:用于描述方法

    5.PACKAGE:用于描述包

    6.PARAMETER:用于描述参数

    7.TYPE:用于描述类、接口(包括注解类型) 或enum声明

例如:

[java] view plain copy print?
  1. @Target(ElementType.TYPE)  
  2. public @interface MyAnnotation {  
  3.     //类名注解,默认即为当前类名  
  4.     String name() default "className";  
  5. }  

[java] view plain copy print?
  1. import java.lang.annotation.ElementType;  
  2. import java.lang.annotation.Target;  
  3.   
  4. //字段注解  
  5. @Target(ElementType.FIELD)  
  6. public @interface MyAnnotation1 {  
  7.     String name() default "fieldName";            
  8.     String getFieldValue() default "getField";    
  9.     String setFieldValue() default "setField";   
  10. }  


@Retention:描述注解的生命周期,即注解的生效范围。

  取值范围(RetentionPolicy):

   1.SOURCE:在源文件中生效,仅存在java文件中,class文件将会去除注解。

   2.CLASS:在class文件中生效,仅保留在class文件中,运行时无法获取注解。

   3.RUNTIME:在运行时生效,保留在class文件中且运行时可通过反射机制获取。

例如:

[java] view plain copy print?
  1. @Target(ElementType.FIELD) //字段注解  
  2. @Retention(RetentionPolicy.RUNTIME) //在运行期保留注解信息  
  3. public @interface MyAnnotation1 {  
  4.     String name() default "fieldName";            
  5.     String getFieldValue() default "getField";    
  6.     String setFieldValue() default "setField";   
  7. }  


@Documented:用于指定javac生成API时显示该注解信息。

例如:

[java] view plain copy print?
  1. @Target(ElementType.FIELD) //字段注解  
  2. @Retention(RetentionPolicy.RUNTIME) //在运行期保留注解信息  
  3. @Documented     //在生成javac时显示该注解的信息  
  4. public @interface MyAnnotation1 {  
  5.     String name() default "fieldName";            
  6.     String getFieldValue() default "getField";    
  7.     String setFieldValue() default "setField";   
  8. }  


@Inherited:标明该注解可以由子类继承,及子类可以继承父类的注解。而默认情况下,子类是不继承父类注解的。

例如:

[java] view plain copy print?
  1. @Target(ElementType.FIELD) //字段注解  
  2. @Retention(RetentionPolicy.RUNTIME) //在运行期保留注解信息  
  3. @Documented     //在生成javac时显示该注解的信息  
  4. @Inherited      //标明MyAnnotation1注解可以被使用它的子类继承  
  5. public @interface MyAnnotation1 {  
  6.     String name() default "fieldName";            
  7.     String getFieldValue() default "getField";    
  8.     String setFieldValue() default "setField";   
  9.     public enum FieldValue{MYTEST,MYFIELD,MYVALUE};  
  10.     FieldValue  realVale() default FieldValue.MYFIELD;  
  11. }  

二、读取注解

    通过反射机制我们可以读取注解信息。java在java.lang.reflect包下新增了AnnotatedElement接口,该接口定义了可以接受注解的元素为:Class(类)、Constructor(构造器)、Field(字段)、Method(方法)、Package(包)。

    AnnotatedElement是所有注解元素的父接口,所有的注解元素都可以通过某个类反射获取AnnotatedElement对象,该对象有一下4个方法来访问Annotation信息。

(1)<T extends Annotation> T getAnnotation(Class<T> annotationClass)

     返回该程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null。


(2)Annotation[] getAnnotations():返回该程序元素上存在的所有注解。


(3)boolean isAnnotationPresent(Class<?extends Annotation> annotationClass)

    判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false.


(4)Annotation[] getDeclaredAnnotations()

    返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注释。(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。

例如:

注解:

[java] view plain copy print?
  1. package com.dhcc.iscp.web.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.   
  8. @Target(ElementType.TYPE)  
  9. @Retention(RetentionPolicy.RUNTIME) //在运行期保留注解信息  
  10. public @interface MyAnnotation {  
  11.     //类名注解,默认即为当前类名  
  12.     String name() default "className";  
  13. }  


[java] view plain copy print?
  1. package com.dhcc.iscp.web.annotation;  
  2.   
  3. import java.lang.annotation.Documented;  
  4. import java.lang.annotation.ElementType;  
  5. import java.lang.annotation.Inherited;  
  6. import java.lang.annotation.Retention;  
  7. import java.lang.annotation.RetentionPolicy;  
  8. import java.lang.annotation.Target;  
  9.   
  10.   
  11. @Target(ElementType.FIELD) //字段注解  
  12. @Retention(RetentionPolicy.RUNTIME) //在运行期保留注解信息  
  13. @Documented     //在生成javac时显示该注解的信息  
  14. @Inherited      //标明MyAnnotation1注解可以被使用它的子类继承  
  15. public @interface MyAnnotation1 {  
  16.     String name() default "fieldName";            
  17.     String getFieldValue() default "getField";    
  18.     String setFieldValue() default "setField";   
  19.     public enum FieldValue{MYTEST,MYFIELD,MYVALUE};  
  20.     FieldValue  realValue() default FieldValue.MYFIELD;  
  21. }  

实体类:

[java] view plain copy print?
  1. package com.dhcc.iscp.web.annotation;  
  2.   
  3. import com.dhcc.iscp.web.annotation.MyAnnotation1.FieldValue;  
  4.   
  5. @MyAnnotation(name="myTest")  
  6. public class MyTest {  
  7.   
  8.     @MyAnnotation1  
  9.     String myTest;  
  10.       
  11.     @MyAnnotation1(name="test",getFieldValue="1",setFieldValue="2",realValue=FieldValue.MYVALUE)  
  12.     String testValue;  
  13.   
  14.     public String getMyTest() {  
  15.         return myTest;  
  16.     }  
  17.   
  18.     public void setMyTest(String myTest) {  
  19.         this.myTest = myTest;  
  20.     }  
  21.   
  22.     public String getTestValue() {  
  23.         return testValue;  
  24.     }  
  25.   
  26.     public void setTestValue(String testValue) {  
  27.         this.testValue = testValue;  
  28.     }  
  29.       
  30. }  

测试类:

[java] view plain copy print?
  1. package com.dhcc.iscp.web.annotation;  
  2.   
  3. import java.lang.annotation.Annotation;  
  4. import java.lang.reflect.Field;  
  5. import java.lang.reflect.Method;  
  6.   
  7. public class TestAnnotation {  
  8.     public static void main(String[] args){  
  9.         MyTest myTest = new MyTest();  
  10.           
  11.         Annotation[] annotations = myTest.getClass().getAnnotations();  //获取类的所有注解  
  12.         for(Annotation anno:annotations){  
  13.             if(anno instanceof MyAnnotation){  
  14.                 MyAnnotation myAnnotation = (MyAnnotation)anno;  
  15.                 System.out.println("className:"+myAnnotation.name());  
  16.             }else if(anno instanceof MyAnnotation1){  
  17.                 MyAnnotation1 myAnnotation1 = (MyAnnotation1)anno;  
  18.                 System.out.println("FiledName:"+myAnnotation1.name());  
  19.                 System.out.println("setFieldValue"+myAnnotation1.setFieldValue());  
  20.                 System.out.println("getFieldValue"+myAnnotation1.getFieldValue());  
  21.                 System.out.println("realValue"+myAnnotation1.realValue());  
  22.             }  
  23.         }  
  24.           
  25.         Field[] fields = myTest.getClass().getDeclaredFields();//获取所有注解字段  
  26.         for(Field field:fields){  
  27.             if(field.isAnnotationPresent(MyAnnotation1.class)){  
  28.                 MyAnnotation1 myAnno = (MyAnnotation1)field.getAnnotation(MyAnnotation1.class);  
  29.                 System.out.println(field.getName()+"-name:"+myAnno.name());  
  30.                 System.out.println(field.getName()+"-getFieldValue:"+myAnno.getFieldValue());  
  31.                 System.out.println(field.getName()+"-setFieldValue:"+myAnno.setFieldValue());  
  32.                 System.out.println(field.getName()+"-realValue:"+myAnno.realValue());  
  33.             }  
  34.         }  
  35.           
  36.         Method[] methods = myTest.getClass().getMethods();//获取所有方法  
  37.         for(Method method:methods){  
  38.             if(method.isAnnotationPresent(MyAnnotation1.class)){  
  39.                 MyAnnotation1 myAnno1 = (MyAnnotation1)method.getAnnotation(MyAnnotation1.class);  
  40.                 System.out.println(myAnno1.getClass());  
  41.             }  
  42.         }  
  43.     }  
  44. }  


测试结果:

Spring自定义注解

三、自定义注解

自定义注解是通过@interface来声明的,其中的每一个方法实际上是声明了一个配置参数,参数名称即为方法名,参数类型即为返回值类型。


自定义注解的格式:

public @interface 注解名{定义体}


注解参数可支持的类型:

  1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)
  2.String类型
  3.Class类型
  4.enum类型
  5.Annotation类型
  6.以上所有类型的数组


注解参数的定义规则:

  a.只能使用public或默认2种访问修饰,例如:String getName();这里getName()就是使用了默认访问权限。

  b.参数类型只能使用上面提到的6种情况

  c.如果只有一个参数成员,最好将参数名定义为:value()。

  d.注解元素必须有确定值,要么在定义的时候设置默认值,要么在使用注解的时候设置参数值。