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

显然,$Proxy1实现了Counter接口,它在代码的最后部分使用了静态代码块实例化了成员方法的Method实例,在前面的代码对这些Method进行了缓存,在调用成员方法的时候都是直接委托到InvocationHandler(AnnotationInvocationHandler)实例完成调用。我们在分析AnnotationInvocationHandler的时候看到,它只用到了Method的名称从Map从匹配出成员方法的结果,因此调用过程并不是反射调用,反而是直接的调用,效率类似于通过Key从Map实例中获取Value一样,是十分高效的。

小结

既然知道了注解的底层原理,我们可以编写一个"注解接口"和InvocationHandler实现来简单模拟整个过程。先定义一个接口:

public interface CounterAnnotation extends Annotation {

int count();
}InvocationHandler的简单实现:

public class CounterAnnotationInvocationHandler implements InvocationHandler {

private final Map<String, Object> memberValues;
    private final Class<? extends Annotation> clazz;

public CounterAnnotationInvocationHandler(Map<String, Object> memberValues, Class<? extends Annotation> clazz) {
        this.memberValues = memberValues;
        this.clazz = clazz;
    }

@Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodName = method.getName();
        Object value;
        switch (methodName) {
            case "toString":
                value = super.toString();
                break;
            case "hashCode":
                value = super.hashCode();
                break;
            case "equals":
                value = super.equals(args[0]);
                break;
            case "annotationType":
                value = clazz;
                break;
            default:
                value = memberValues.get(methodName);
        }
        return value;
    }
}

编写一个main方法:

public class CounterAnnotationMain {

public static void main(String[] args) throws Exception{
        //这里模拟了注解成员属性从常量池解析的过程
        Map<String,Object> values = new HashMap<>(8);
        values.put("count", 1);
        //生成代理类
        CounterAnnotation proxy = (CounterAnnotation)Proxy.newProxyInstance(CounterAnnotationMain.class.getClassLoader(),
                new Class[]{CounterAnnotation.class},
                new CounterAnnotationInvocationHandler(values, CounterAnnotation.class));
        System.out.println(proxy.count());
    }
}
//运行后控制台输出:1

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

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