java 注解 与自定义使用

java注解基本概念

定义:注解(Annotation),也叫做元数据,是一种代码级别的说明。从jdk1.5之后引入的一个特性,与类,接口,枚举是在同一个层次。它可以声明在包,类,字段,方法,局部变量,方法参数等的前面,用来对这些被注解标注的元素进行说明,注释。

java注解分类

  • 编写文档: 通过代码里面的注解标示生成doc文档。比如swagger

  • 代码分析: 通过代码里面的注解标示对代码进行分析。[使用反射]

  • 编译检查: 通过代码里标识的注解让编译器能够实现基本的编译检查。比如@override

    我们自定义注解主要是进行代码分析。

jdk中预定义的注解

  • @Override : 检测被该注解标注的方法是否是继承自父类的。
  • @Deprecated : 该注解标注的内容,表示已经过时。未删除,但是不推荐使用,仅仅为了保持向下兼容性。
  • @SuppressWarnings : 压制对该方法的警告。

jdk中四种用于定义新注解的元注解

注解名称 相关说明
@Target 表示该注解可以用在什么位置。 ElementType的取值有:
          TYPE: 表示可以注解在类上。
          METHOD:表示可以作用在方法上。
          FIELD: 表示可以作用在成员变量上。
          PARAMETER: 表示可以作用在方法参数上。
          LOCAL_VARIABLE; 表示可以作用在局部变量上。
@Retention
     表示需要在什么级别保存该注解信息。
          SOURCE: 注解将在编译器丢弃。
          CLASS: 注解在class文件中可用,但是会被JVM丢弃。
          RUNTIME: VM将在运行时保留注释,因此可以通过反射机制读取注解的信息。 自定义注解一般用 RUNTIME。
@Documented
    将该注解包含在javadoc中。
@Inherited
    允许子类继承父类中的注解。

java注解的本质

  • 注解的格式:
public @interface  注解名称{
	...
}
  • 注解的本质:
#上面定义的注解,实际上会被转换成一个集成了 java.lang.annotation.Annotation 接口的接口。

public interface MyAnno extends java.lang.annotation.Annotaion {

}
  • 注解的属性:
#注解的属性,就是接口中定义的抽象方法。	

java注解的参数说明

  • 注解元素可用的类型
1.、所有基本类型(int, float, boolean).
2.、String
3.、枚举enum
4、 自定义类Class
5、 注解类型Annotation,注解可以作为元素的类型,也就是说注解可以嵌套。
  • 注解的默认值: 注解的元素不能没有不确定的值。所以说元素要么在注解时提供元素的值,要么就必须制定默认值。
@Target( ElementType.METHOD )
@Retention( RetentionPolicy.RUNTIME )
public @interface Test {
	#注解的属性,对应于接口中定义的方法。且方法后面可以通过default来提供默认值。
	public int id() defalut -1;
	public String description() default '';
}

java注解的自定义

  • 关于类上的注解
#1.定义作用在类上的注解:
import java.lang.annotation.*;
//只作用在类上
@Target( ElementType.TYPE )
//运行时期有效
@Retention( RetentionPolicy.RUNTIME )
@Documented
@Inherited
public @interface ClassAnnotation {
    public String value() default "";
}


#2.在类上标注@ClassAnnotaion,且在启动时处理该注解。
#  凡是有@ClassAnnotaion注解的类,都进行对象生成,并且设置id名称。 
@ClassAnnotation("test1Controller")
public class Test1Controller {

    private Integer a = 10;
    public Integer getA() {
        return a;
    }

    public static void main(String[] args) throws Exception {
        HashMap map = new HashMap();
        Class clz = Test1Controller.class;
        Annotation clzList[] = clz.getAnnotations();
        for ( int i=0; i<clzList.length; i++ ){
            Annotation item = clzList[i];
            if ( item.annotationType().toString().equals("interface com.mz.controller.ClassAnnotation")  ){
                //发现是@classAnnotation,那么就进行对象创建
                ClassAnnotation classAnnotation = (ClassAnnotation) item;
                //获取要生成的对象的id值
                String name = classAnnotation.value();
                System.out.println(classAnnotation.value());
                //生成该类对象
                Test1Controller test1Controller = (Test1Controller)Class.forName("com.mz.controller.Test1Controller").newInstance();
                System.out.println(test1Controller.getA());

                //获取注解中的value属性
                map.put(name, test1Controller);
            }
        }
    }
}
  • 关于方法上的注解
#1.定义作用在方法上的注解

import java.lang.annotation.*;

@Target( ElementType.METHOD )
@Retention( RetentionPolicy.RUNTIME )
@Documented
@Inherited
public @interface MethodAnnotation {

    /**
     *  被@MethodAnnotation注解标注的方法,会被放在一个映射中。
     *  然后可以通过key去调用这个对象,以及方法。
     * */

    public String value() default "";
}


#2.注解标注在方法上,并且放到一个映射中。
@ClassAnnotation("test1Controller")
public class Test1Controller {

    private Integer a = 10;

    public Integer getA() {
        return a;
    }

    @MethodAnnotation("/test")
    public void test() throws Exception {

        System.out.println("这就是一个测试");
    }


    public static void main(String[] args) throws Exception {

        HashMap map = new HashMap();
        Class clz = Test1Controller.class;
        Annotation clzList[] = clz.getAnnotations();
        for ( int i=0; i<clzList.length; i++ ){
            Annotation item = clzList[i];
            if ( item.annotationType().toString().equals("interface com.mz.controller.ClassAnnotation")  ){
                //发现是@classAnnotation,那么就进行对象创建
                ClassAnnotation classAnnotation = (ClassAnnotation) item;
                //获取要生成的对象的id值
                String name = classAnnotation.value();
                System.out.println(classAnnotation.value());
                //生成该类对象
                Test1Controller test1Controller = (Test1Controller)Class.forName("com.mz.controller.Test1Controller").newInstance();
                System.out.println(test1Controller.getA());


                
                //获取注解中的value属性
                map.put(name, test1Controller);

                /*
                *  如果该类的方法上存在@MethodAnnation注解,那么外界如果访问该字段,那么就
                *
                * */
                Method method[] = clz.getMethods();
                for ( int j =0 ; j<method.length; j++ ){

                    if (method[j].getName() == "test"){
                        Annotation annotation = method[j].getAnnotation(MethodAnnotation.class);
                        method[j].invoke(test1Controller);
                        System.out.println(annotation.annotationType());
                        if ( annotation.annotationType().toString().equals("interface com.mz.controller.MethodAnnotation") ){
                            //此时将对象,方法名,方法参数等记录作为value放到map中,将annotation中的值当做key进行存放。
                            MethodAnnotation methodAnnotation = (MethodAnnotation) annotation;
                            System.out.println(methodAnnotation.value());
                        }
                    }
                }
            }
        }
    }
}


  • 关于方法参数上的注解
#1.方法参数上的注解定义
package com.mz.controller;
import java.lang.annotation.*;

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME )
@Documented
@Inherited
public @interface ParameterAnnotation {
    public String value() default "";
}


#2.在方法参数上进行注解标注,然后获取该方法参数上的注解,并进行处理
package com.mz.controller;


import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;

/**
     这是一个简单的测试类.

     <p>这是一个简单的测试类,里面含有三个模块,一个是用于ui测试 {@code string},一个用于单元测试 @{code Test1Controller},还一个暂未完成. </p>

      @author  mengze
      @date   2019-10-12
      @since   1.5
      @version 1.0
 */

@ClassAnnotation("test1Controller")
public class Test1Controller {

    private Integer a = 10;

    public Integer getA() {
        return a;
    }

    @MethodAnnotation("/test")
    public void test( @ParameterAnnotation() Integer a ) throws Exception {

        System.out.println("这就是一个测试");
    }


    public static void main(String[] args) throws Exception {

        HashMap map = new HashMap();
        Class clz = Test1Controller.class;
        Annotation clzList[] = clz.getAnnotations();
        for ( int i=0; i<clzList.length; i++ ){
            Annotation item = clzList[i];
            if ( item.annotationType().toString().equals("interface com.mz.controller.ClassAnnotation")  ){
                //发现是@classAnnotation,那么就进行对象创建
                ClassAnnotation classAnnotation = (ClassAnnotation) item;
                //获取要生成的对象的id值
                String name = classAnnotation.value();
                System.out.println(classAnnotation.value());
                //生成该类对象
                Test1Controller test1Controller = (Test1Controller)Class.forName("com.mz.controller.Test1Controller").newInstance();
                System.out.println(test1Controller.getA());



                //获取注解中的value属性
                map.put(name, test1Controller);

                /*
                *  如果该类的方法上存在@MethodAnnation注解,那么外界如果访问该字段,那么就
                *
                * */
                Method method[] = clz.getMethods();
                for ( int j =0 ; j<method.length; j++ ){

                    Method temp = method[j];
                    if (method[j].getName() == "test"){
                        Annotation annotation = method[j].getAnnotation(MethodAnnotation.class);
//                        method[j].invoke(test1Controller);
                        System.out.println(annotation.annotationType());
                        if ( annotation.annotationType().toString().equals("interface com.mz.controller.MethodAnnotation") ){
                            //此时将对象,方法名,方法参数等记录作为value放到map中,将annotation中的值当做key进行存放。
                            MethodAnnotation methodAnnotation = (MethodAnnotation) annotation;
                            System.out.println(methodAnnotation.value());
                        }

                        Parameter parameter[] = method[j].getParameters();
                        for ( Parameter pTemp : parameter ){

                            //获取方法上的参数,然后判断该参数上是否有注解;
                            //如果方法的参数上有注解,表明参数是何种方式接受,或者说这个参数需要接受一个什么值
                            System.out.println(pTemp.getName());
                            Annotation annotation1 = pTemp.getAnnotation(ParameterAnnotation.class);
                            System.out.println(annotation1);
                        }
                    }
                }
            }
        }
    }
}
  • 关于成员变量上的注解
#1. 定义使用在成员变量上的注解
package com.mz.controller;
import java.lang.annotation.*;
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME )
@Documented
@Inherited
public @interface ParameterAnnotation {

    public String value() default "";
}


#2. 使用@MemberAnnotation注解标注成员属性,并且处理
@ClassAnnotation("test1Controller")
public class Test1Controller {

    @MemberAnnotation("20")
    private Integer a = 0;

    public Integer getA() {
        return a;
    }

    public static void main(String[] args) throws Exception {

        Class clz = Test1Controller.class;
        Annotation annotation =  clz.getAnnotation(ClassAnnotation.class);
        //类上面有@ClassAnnotation
        if ( annotation != null ){
            //因为类上有指定的注解,那么生成该类的对象.
            Test1Controller test1Controller = Test1Controller.class.newInstance();
            Field field[] = clz.getDeclaredFields();
            for (Field fItem : field ){
                MemberAnnotation memberAnnotation =  fItem.getAnnotation(MemberAnnotation.class);
                //成员属性上存在该注解
                if ( memberAnnotation != null ){
                    fItem.set(test1Controller,  new Integer(memberAnnotation.value() ));
                    System.out.println(test1Controller.getA());
                }
            }
        }
    }
}

java注解常使用场景

 todo  未完待续,太晚熬不住了。
发布了58 篇原创文章 · 获赞 34 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_36723759/article/details/104072679