/** * Creates a proxy instance for the supplied annotation type and values. * * @param classLoader The class loader that should be used for loading the annotation's values. * @param annotationType The annotation's type. * @param values The values that the annotation contains. * @param <S> The type of the handled annotation. * @return A proxy for the annotation type and values. * @throws ClassNotFoundException If the class of an instance that is contained by this annotation could not be found. */ @SuppressWarnings("unchecked") public static <S extends Annotation> S of(ClassLoader classLoader, Class<S> annotationType, Map<String, ? extends AnnotationValue<?, ?>> values) throws ClassNotFoundException { LinkedHashMap<Method, AnnotationValue.Loaded<?>> loadedValues = new LinkedHashMap<Method, AnnotationValue.Loaded<?>>(); for (Method method : annotationType.getDeclaredMethods()) { AnnotationValue<?, ?> annotationValue = values.get(method.getName()); loadedValues.put(method, (annotationValue == null ? defaultValueOf(method) : annotationValue).load(classLoader)); } return (S) Proxy.newProxyInstance(classLoader, new Class<?>[]{annotationType}, new AnnotationInvocationHandler<S>(annotationType, loadedValues)); }