首页 > 代码库 > JavaWeb【自定义注解】

JavaWeb【自定义注解】

 

 

 

一。自定义注解(形体)

 

情形一: 单一注解

  定义

public @interface MyAnnotation {    //定义注解属性:    //属性类型 属性名() default 默认值;    //String name() default "自定义名字";     String name();    int age() default 20;    //注解属性类型:基本类型,String,Class,注解,枚举,和 前面几种类型的一维数组    //Student student; error:The blank final field student may not have been initialized}

  使用:

class Demo{    //给注解赋值    @MyAnnotation(name="段哥哥",sex="男")    public void hello(){        System.out.println("hello");    }    }

 

情形二:注解的嵌套

  定义

public @interface MyAnnotation2 {    String url() default "";    MyAnnotation[] myAnnotations();}

  使用

@MyAnnotation2(myAnnotations={@MyAnnotation(name="注解一",sex="女"),@MyAnnotation(name="注解二",sex="男")})class Demo2{    @MyAnnotation2(myAnnotations={@MyAnnotation(name="注解一",sex="女"),@MyAnnotation(name="注解二",sex="男")})    public void hello(){        System.out.println("hello");    }}

 

情形三:特殊的注解属性value

  定义

public @interface MyAnnotation3 {    String name() default "name";    String value() default "男";}

  使用

class Demo3{    @MyAnnotation3("who")    public void hello(){}}

  ps:当使用注解没有指定给哪个属性赋值时,默认是value属性,所以上面的who就赋值给了value属性。

 

情形四:数组类型的value

  定义

public @interface MyAnnotation3 {    String[] value() default ""; }

  使用

class Demo3{    //给数组指定一个值    @MyAnnotation3("a")    public void hello(){            }    //给数组指定二个值    { }的使用    @MyAnnotation3({"a","b"})    public void hello2(){            }}

 


  我们自定义的所有注解类型都是java.lang.Annotation接口的子类,既然子类,那么Annotation接口中的方法我们都可以使用


 

 

二。注解的反射(灵魂)

 

java.lang.reflect.AnnotatedElement 

  •   <T extends Annotation> T getAnnotation(Class<T> annotationClass):该方法获取指定Class类型的注解实例的引用
  •   Annotation[] getAnnotations():获取所有的注解,包含继承下来的
  •   Annotation[] getDeclaredAnnotations();获取自己直接使用的注解,不包含继承下来的
  •   boolean isAnnotaionPresent(Class<? extends Annotaion> annotionType):看看指定的注解在不在

  谁来调用这些方法,AnnotatedElement接口的实现类,有以下这几个AnnotatedElement的实现类:

  •   Class:表示一个类型
  •   Method:表示一个方法
  •   Field:表示一个字段
  •   Constructor:表示一个构造方法
  •   etc

 

类的三种状态

  注解也就是类,只要是类就有三种状态

一。SOURCE源代码(*.java)

  存在磁盘上

二。CLASS字节码(*.class)

  存在磁盘上

三。RUNTIME内存中的class

  从磁盘上加载到内存上。这就是类加载器所做的

 

  结论:在我们之前定义的注解,也就是类 处在CLASS字节码状态,存在于磁盘上

  验证上面的结论:

技术分享
        Class class1=S.class;        Method[] methods=class1.getMethods();        for(Method m:methods){            boolean flag=m.isAnnotationPresent(MyTest.class);            System.out.println(m.getName()+"有没有"+flag);        }
View Code

  控制台输出的都为false

 

注解的生命周期-元注解

  元注解:在注解上面定义的注解

  元注解的种类

  @Rentention

     作用;改变注解的存活范围

@Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.ANNOTATION_TYPE)public @interface Retention {    RetentionPolicy value();}
技术分享
public enum RetentionPolicy {    /**     * Annotations are to be discarded by the compiler.     */    SOURCE,    /**     * Annotations are to be recorded in the class file by the compiler     * but need not be retained by the VM at run time.  This is the default     * behavior.     */    CLASS,    /**     * Annotations are to be recorded in the class file by the compiler and     * retained by the VM at run time, so they may be read reflectively.     *     * @see java.lang.reflect.AnnotatedElement     */    RUNTIME}
RetentionPolicy

     使用:在注解的定义上,当我们运行下面代码,控制台上就会看到true了

技术分享
        Class class1=S.class;        Method[] methods=class1.getMethods();        for(Method m:methods){            boolean flag=m.isAnnotationPresent(MyTest.class);            System.out.println(m.getName()+"有没有"+flag);        }
View Code

 

  但是单单使用了@Rentention只是改变了存活范围,该注解仅仅只能注解方法,要想在类上使用,我们需要在注解的位置上做限定

 

  @Target

     作用:注解应用的位置

@Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.ANNOTATION_TYPE)public @interface Target {    ElementType[] value();}
技术分享
public enum ElementType {    /** Class, interface (including annotation type), or enum declaration */    TYPE,    /** Field declaration (includes enum constants) */    FIELD,    /** Method declaration */    METHOD,    /** Parameter declaration */    PARAMETER,    /** Constructor declaration */    CONSTRUCTOR,    /** Local variable declaration */    LOCAL_VARIABLE,    /** Annotation type declaration */    ANNOTATION_TYPE,    /** Package declaration */    PACKAGE}
ElementType

 

  @Documented:应用了该注解的注解的类,对应的文档中是否显示注解

  @Inherited:被注解的注解的类 的子类,会自动注解子类

  

 

  结论:仅仅定义注解只是定义了形体,如果想要发挥作用,就是需要反射,而反射所依赖的一些东西,需要元注解去注解

 


 

 

三。注解的意义

 

  在开发中,通过一些xml配置来指挥程序的运行,

    缺点:开发不直观

    优点:避免硬编码

  注解是来替代xml作为配置用的

    优点:直观,开发简便,快速

    缺点:硬编码

JavaWeb【自定义注解】