注解的原理

注解的定义方式为

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
    String name() default "ryy";
}

@Target和@Retention为源注解,就是给我们自己定义的注解说明一个生效时间以及生效位置的注解,jdk自带。

这里不重点介绍,主要介绍下我们定义的注解到底是个什么呢?它又能做些什么呢?

看@interface 这种类型 就比 interface 多一个 @,其实注解本质是一个继承了Annotation的特殊接口,也就是说它也是一个interface。

这个interface在程序运行时都做了些什么?

在获取注解对象时,实际上是获取的它的代理对象。

interface Human{
    void say();
}
@TestAnnotation
class Student implements Human{

    @Override
    public void say() {
        System.out.println("student 说:");
    }
}

这里定义了一个Student类,它上边加了一个之前定义好的注解TestAnnotation。

public class Test {
    public static void main(String[] args) {
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        Student student = new Student();
        TestAnnotation annotation = student.getClass().getAnnotation(TestAnnotation.class);
        System.out.println(annotation.name());
    }
}

启动程序,new一个Student对象,并将它的TestAnnotation对象拿出来。

跟进getAnnotation方法,可以看到,实际上是从一个Map中把我们定义的注解取出来(AnnotationData是Class类中的一个静态内部类)。

    // annotation data that might get invalidated when JVM TI RedefineClasses() is called
    private static class AnnotationData {
        final Map<Class<? extends Annotation>, Annotation> annotations;
        .........
    }

这个Map中存的是一些什么对象?

使用了

System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

所以,在程序执行中生成的代理类,都会被导出。看一下生成的代理类。

public final class $Proxy1 extends Proxy implements TestAnnotation {
    private static Method m1;
    private static Method m3;
    private static Method m2;
    private static Method m4;
    private static Method m0;

    public $Proxy1(InvocationHandler var1) throws  {
        super(var1);
    }



    public final String name() throws  {
        try {
            return (String)super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }



    public final Class annotationType() throws  {
        try {
            return (Class)super.h.invoke(this, m4, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }




}

可以看到,生成了一个类实现了我们自己定义的注解TestAnnotation,并且实现了它的抽象方法name()

name()方法中调用了父类的InvocationHandler的invoke方法,注解使用的InvocationHandler是

class AnnotationInvocationHandler implements InvocationHandler, Serializable

看到这个类中的invoke()方法中,如果是自己定义的方法,比如这个name(),就会从它自己的

private final Map<String, Object> memberValues 中去通过方法名去get(),比如"name"。

而这个 memberValues就是创建代理对象时通过解析RuntimeVisibleAnnotations时得到并传给AnnotationInvocationHandler的。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值