元注解解析(框架底层怎么使用的注解?)


个人主页

Annotation(注解)

从JDK 1.5开始, Java增加了对元数据(MetaData)的支持,也就是 Annotation(注解)。

注解其实就是代码里的特殊标记,它用于替代配置文件:传统方式通过配置文件告诉类如何运行,有了注解技术后,开发人员可以通过注解告诉类如何运行。在Java技术里注解的典型应用是:可以通过反射技术去得到类里面的注解,以决定怎么去运行类。

注解可以标记在包、类、属性、方法,方法参数以及局部变量上,且同一个地方可以同时标记多个注解。

// 抑制编译期的未指定泛型、未使用和过时警告
   @SuppressWarnings({ "rawtypes", "unused", "deprecation" })
// 重写
   @Override

meta-annotation(元注解)

除了直接使用JDK 定义好的注解,我们还可以自定义注解,在JDK 1.5中提供了4个标准的用来对注解类型进行注解的注解类,我们称之为 meta-annotation(元注解),他们分别是:

  • @Target
  • @Retention
  • @Documented
  • @Inherited

我们可以使用这4个元注解来对我们自定义的注解类型进行注解。

@Target注解

Target注解的作用是:描述注解的使用范围(即:被修饰的注解可以用在什么地方) 。

Target注解用来说明那些被它所注解的注解类可修饰的对象范围:注解可以用于修饰 packages、types(类、接口、枚举、注解类)、类成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数),在定义注解类时使用了@Target 能够更加清晰的知道它能够被用来修饰哪些对象,它的取值范围定义在ElementType 枚举中。

public enum ElementType {
 
    TYPE, // 类、接口、枚举类
 
    FIELD, // 成员变量(包括:枚举常量)
 
    METHOD, // 成员方法
 
    PARAMETER, // 方法参数
 
    CONSTRUCTOR, // 构造方法
 
    LOCAL_VARIABLE, // 局部变量
 
    ANNOTATION_TYPE, // 注解类
 
    PACKAGE, // 可用于修饰:包
 
    TYPE_PARAMETER, // 类型参数,JDK 1.8 新增
 
    TYPE_USE // 使用类型的任何地方,JDK 1.8 新增
 
}

@Retention注解

Reteniton注解的作用是:描述注解保留的时间范围(即:被描述的注解在它所修饰的类中可以被保留到何时) 。

Reteniton注解用来限定那些被它所注解的注解类在注解到其他类上以后,可被保留到何时,一共有三种策略,定义在RetentionPolicy枚举中。

public enum RetentionPolicy {
 
    SOURCE,    // 源文件保留
    CLASS,       // 编译期保留,默认值
    RUNTIME   // 运行期保留,可通过反射去获取注解信息
}

@Documented注解

Documented注解的作用是:描述在使用 javadoc 工具为类生成帮助文档时是否要保留其注解信息。

@Inherited注解

Inherited注解的作用是:使被它修饰的注解具有继承性(如果某个类使用了被@Inherited修饰的注解,则其子类将自动具有该注解)。

定义注解中的属性

基本形式:类型 属性名称();

比如:String name();

特别注意:

  • 属性值后边有一个括号!!!这个是和之前定义属性不一样的地方
  • 注解的属性的类型只能是:基本类型、String、Class、枚举、注解类型及以上类型的一维数组。

定义注解属性的默认值: 类型 属性名称() default 默认值;

比如:String name() default "zhangsan";

举例:定义注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
 
    String value() default "abc";
 
    String name() default "zhangsan";
 
}

注解属性定义完以后,使用注解:@MyAnnotation(value = “123”,name = “lisi”)

举例:使用注解

public class Test {
  
    @MyAnnotation(value = "123",name = "lisi")
    public static void test(){
        System.out.println("这是test");
    }
 
}

框架底层怎么使用的注解?

利用反射获取方法上的注解,并获取对应的值

package com.exam.util;

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 
 */
public class Test {
    public static void main(String[] args) throws Exception {

        Class clazz = Class.forName("com.exam.util.Test");
        Method[] ms = clazz.getMethods();
        for (Method m : ms) {
            if(m.isAnnotationPresent(MyAnnotation.class)){
                String value = m.getAnnotation(MyAnnotation.class).value();
                String name = m.getAnnotation(MyAnnotation.class).name();
                System.out.println("value:"+value);
                System.out.println("name:"+name);
            }
        }
    }

    @MyAnnotation(value = "123",name = "lisi")
    public static void test(){
        System.out.println("这是test");
    }

}
/**
 * @author 
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
 @interface MyAnnotation {

    String value() default "abc";

    String name() default "zhangsan";

}

最后看下输出打印的结果:

image.png

可以看到,我们自定义个一个注解,然后在方法上使用了自己的注解,最后通过反射拿到这个方法上的注解和属性值

由于这里只是个demo,所以只是拿到值后进行了打印,并没有一些复杂的操作

但是,在实际应用中,拿到了方法上自定义的注解和属性值后,那就可以根据你具体的业务逻辑进行一些对应的操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值