JDK中注解的底层实现(3)

public Object invoke(Object var1, Method var2, Object[] var3) {
        //获取当前执行的方法名称
        String var4 = var2.getName();
        Class[] var5 = var2.getParameterTypes();
        if (var4.equals("equals") && var5.length == 1 && var5[0] == Object.class) {
            return this.equalsImpl(var3[0]);
        } else if (var5.length != 0) {
            throw new AssertionError("Too many parameters for an annotation method");
        } else {
            byte var7 = -1;
            switch(var4.hashCode()) {
            case -1776922004:
                if (var4.equals("toString")) {
                    var7 = 0;
                }
                break;
            case 147696667:
                if (var4.equals("hashCode")) {
                    var7 = 1;
                }
                break;
            case 1444986633:
                if (var4.equals("annotationType")) {
                    var7 = 2;
                }
            }
            switch(var7) {
            case 0:
                return this.toStringImpl();
            case 1:
                return this.hashCodeImpl();
            case 2:
                return this.type;
            default:
                //利用方法名称从memberValues获取成员属性的赋值
                Object var6 = this.memberValues.get(var4);
                if (var6 == null) {
                    throw new IncompleteAnnotationException(this.type, var4);
                } else if (var6 instanceof ExceptionProxy) {
                    throw ((ExceptionProxy)var6).generateException();
                } else {
                    //这一步就是注解成员属性返回值获取的实际逻辑
                    //需要判断是否数据,如果是数据需要克隆一个数组
                    //不是数组直接返回
                    if (var6.getClass().isArray() && Array.getLength(var6) != 0) {
                        var6 = this.cloneArray(var6);
                    }
                    return var6;
                }
            }
        }
    }
//忽略其他方法   

这里需要重点注意一下的是:AnnotationInvocationHandler的成员变量Map<String, Object> memberValues存放着注解的成员属性的名称和值的映射,注解成员属性的名称实际上就对应着接口中抽象方法的名称,例如上面我们定义的@Counter注解生成代理类后,它的AnnotationInvocationHandler实例中的memberValues属性存放着键值对count=1。

既然知道了注解底层使用了JDK原生的Proxy,那么我们可以直接输出代理类到指定目录去分析代理类的源码,有两种方式可以输出Proxy类的源码:

1、通过Java系统属性设置System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");。

2、通过-D参数指定,其实跟1差不多,参数是:-Dsun.misc.ProxyGenerator.saveGeneratedFiles=true。

这里使用方式1,修改一下上面用到的main方法:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/65f9ab26f1015e214c286cfe64fc204b.html