java注解开发

一、JAVA注解

1、java注解的定义

Java注解是附加在代码中的一些元信息,用于一些工具在编译加载class运行时进行解析和使用,起到说明、配置的功能。

注解相关类都包含在java.lang.annotation包中。

2.2 JDK元注解

元注解用于修饰其他的注解

@Target:指定被修饰的Annotation可以放置的位置(被修饰的目标)

  @Target(ElementType.TYPE)                      //接口、类
  @Target(ElementType.FIELD)                     //属性
  @Target(ElementType.METHOD)                    //方法
  @Target(ElementType.PARAMETER)                 //方法参数
  @Target(ElementType.CONSTRUCTOR)               //构造函数
  @Target(ElementType.LOCAL_VARIABLE)            //局部变量
  @Target(ElementType.ANNOTATION_TYPE)           //注解
  @Target(ElementType.PACKAGE)                   //包 
 
  注:可以指定多个位置,例如:@Target({ElementType.METHOD, ElementType.TYPE}),也就是此注解可以在方法和类上面使用

@Retention:定义注解的保留策略

  @Retention(RetentionPolicy.SOURCE)             //注解仅存在于源码中,在class字节码文件中不包含
  @Retention(RetentionPolicy.CLASS)              //默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得
  @Retention(RetentionPolicy.RUNTIME)            //注解会在class字节码文件中存在,在运行时可以通过反射获取到

@Documented:指定被修饰的该Annotation可以被javadoc工具提取成文档.

@Inherited:指定被修饰的Annotation将具有继承性

2.3 注解的生命周期@Retention

@Retention的3个生命周期

@Retention作用是定义被它所注解的注解保留多久,一共有三种策略,定义在RetentionPolicy枚举中.

从注释上看:

  • source:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;被编译器忽略
  • class:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期
  • runtime:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在

这3个生命周期分别对应于:Java源文件(.java文件) —> .class文件 —> 内存中的字节码。

如何来选择合适的注解生命周期

首先要明确生命周期长度 SOURCE < CLASS < RUNTIME ,所以前者能作用的地方后者一定也能作用。

一般如果需要在运行时去动态获取注解信息,那只能用 RUNTIME 注解(常用);
如果要在编译时进行一些预处理操作,比如生成一些辅助代码(如 ButterKnife),就用 CLASS注解;
如果只是做一些检查性的操作,比如 @Override 和 @SuppressWarnings,则可选用 SOURCE 注解。

2.4 通过反射获取注解

需要通过反射来获取运行时注解,可以从 Package、Class、Field、Method…上面获取,基本方法都一样,几个常见的方法如下:

要使用这些函数必须先通过反射获取到对应的元素:Class、Field、Method 等

/**
* 获取指定类型的注解
*/
public <A extends Annotation> A getAnnotation(Class<A> annotationType);
/**
* 获取所有注解,如果有的话
*/
public Annotation[] getAnnotations();
/**
* 获取所有注解,忽略继承的注解
*/
public Annotation[] getDeclaredAnnotations();
/**
* 指定注解是否存在该元素上,如果有则返回true,否则false
*/
public boolean isAnnotationPresent(Class<? extends Annotation> annotationType);
/**
* 获取Method中参数的所有注解
*/
public Annotation[][] getParameterAnnotations();

二、自定义注解使用示例

2.1 自定义注解

来看下自定义注解的简单使用方式,这里先定义3个运行时注解:

// 适用类、接口(包括注解类型)或枚举
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ClassInfo {
    String value();
}
// 适用field属性,也包括enum常量
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface FieldInfo {
    int[] value();
}
// 适用方法
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MethodInfo {
    String name() default "long";
    String data();
    int age() default 27;
}

2.2 使用

@Component
@ClassInfo("Test Class")
@Slf4j
public class Test {

    @FieldInfo(value = {1, 2})
    public String fieldInfo = "FiledInfo";

    @FieldInfo(value = {10086})
    public int i = 100;

    public static void main(String[] args) {

        final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("annotation");
        final Test test = (Test) context.getBean("test");

        System.out.println(test);

        StringBuffer sb = new StringBuffer();
        Class<?> cls = test.getClass();

        // 获取构造方法
        Constructor<?>[] constructors = cls.getConstructors();

        // 获取指定类型的注解
        sb.append("Class注解:").append("\n");
        ClassInfo classInfo = cls.getAnnotation(ClassInfo.class);
        if (classInfo != null) {
            sb.append(Modifier.toString(cls.getModifiers())).append(" ")
                    .append(cls.getSimpleName()).append("\n");
            sb.append("注解值: ").append(classInfo.value()).append("\n\n");
        }
        sb.append("Field注解:").append("\n");
        Field[] fields = cls.getDeclaredFields();
        for (Field field : fields) {
            FieldInfo fieldInfo = field.getAnnotation(FieldInfo.class);
            if (fieldInfo != null) {
                sb.append(Modifier.toString(field.getModifiers())).append(" ")
                        .append(field.getType().getSimpleName()).append(" ")
                        .append(field.getName()).append("\n");
                sb.append("注解值: ").append(Arrays.toString(fieldInfo.value())).append("\n\n");
            }
        }
        sb.append("Method注解:").append("\n");
        Method[] methods = cls.getDeclaredMethods();
        for (Method method : methods) {
            MethodInfo methodInfo = method.getAnnotation(MethodInfo.class);
            if (methodInfo != null) {
                sb.append(Modifier.toString(method.getModifiers())).append(" ")
                        .append(method.getReturnType().getSimpleName()).append(" ")
                        .append(method.getName()).append("\n");
                sb.append("注解值: ").append("\n");
                sb.append("name: ").append(methodInfo.name()).append("\n");
                sb.append("data: ").append(methodInfo.data()).append("\n");
                sb.append("age: ").append(methodInfo.age()).append("\n");
            }
        }
        System.out.print(sb.toString());

    }

    @MethodInfo(name = "BlueBird", data = "Big")
    void print(String msg) {
        System.out.println(msg);
    }
}

2.2 结果

在这里插入图片描述

参考文章

@Retention注解作用
Java自定义注解开发

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

L-960

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值