Java注解原理

 注解是jdk1.5引入的,本质上是继承了Annotation接口的子接口,主要用于标记信息

一、为什么能在运行时获取到注解的信息?

1)程序启动,加载类信息,生成字节码文件,类的注解信息也在字节码文件

2)当第一次通过反射获取注解时,程序会解析字节码中的注解,通过jdk动态代理创建注解的代理对象,并将注解的数据交给代理对象,这个注解代理对象会被类的Class对象记录每一个Class对象内部都会维护一个注解表,用于缓存类的注解对象

注解代理对象内部有一个代理执行器AnnotationInvocationHandler,简单看一下内部:

class AnnotationInvocationHandler implements InvocationHandler, Serializable {
    //	记录注解的类型
    private final Class<? extends Annotation> type;
    //	记录注解的属性、对应值
    private final Map<String, Object> memberValues;

    AnnotationInvocationHandler(Class<? extends Annotation> type, Map<String, Object> memberValues) {
        //	...	省略
        this.type = type;
        this.memberValues = memberValues;
    }
}

可以看到代理执行器记录了 注解的类型、各个属性及值

在调用注解对象的方法时,会被执行器的invoke方法拦截

class AnnotationInvocationHandler implements InvocationHandler, Serializable {
    private final Class<? extends Annotation> type;
    private final Map<String, Object> memberValues;

    public Object invoke(Object proxy, Method method, Object[] args) {
        //	获取执行注解的哪个方法
        String member = method.getName();

        //	...	省略的一些调用Annotation接口中的方法

        // 通过注解的方法找到对应的值
        Object result = memberValues.get(member);
        //	...
        return result;
    }
}

通过要执行的注解方法,可以从memberValues中找到对应的属性值。

3)以后再获取这个注解的信息就可以直接从类的Class对象的注解表中查询出注解代理对象

二、注解简单使用

import java.lang.annotation.*;
public class Main {
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @interface Component {
        String value() ;
    }
    
    @Component("stu")
    class Student { }
    
    public static void main(String[] args) {
        //  第一次获取注解对象,会从字节码文件中解析出注解信息,创建代理对象,记录在Student的Class对象的注解表中
        Component c1 = Student.class.getAnnotation(Component.class);
        //  第二次获取,直接从Student的Class对象的注解表中获取
        Component c2 = Student.class.getAnnotation(Component.class);
        //  c1与c2本质上是同一个对象,结果为true
        System.out.println(c1 == c2);
        //  这里调用注解代理对象的value方法,会被AnnotationInvocationHandler的invoke方法拦截,然后从成员memberValues中找到对应的属性值
        System.out.println(c1.value());
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值