class AnnoUtil {

	private static Map<String, Annotation> annoCacheMap = new ConcurrentHashMap<>();

	public static <A extends Annotation> A getAnnotation(AnnotatedElement annotatedElement, Class<A> annotationType) {<FILL_FUNCTION_BODY>}

	private static <A extends Annotation> Object getDefaultValue(Class<A> annotationType, String property) {
		try {
			return annotationType.getMethod(property).getDefaultValue();
		}
		catch (Exception e) {
			return null;
		}
	}
}

		String cacheKey = StrUtil.format("{}-{}", annotatedElement, annotationType.getSimpleName());

		if (annoCacheMap.containsKey(cacheKey)){
			return (A)annoCacheMap.get(cacheKey);
		}

		A annotation = AnnotationUtil.getAnnotation(annotatedElement, annotationType);
		if (ObjectUtil.isNull(annotation)) {
			return null;
		}

		Map<String, String> aliasMap = new HashMap<>();
		Map<String, Object> defaultValueMap = new HashMap<>();
		Arrays.stream(ReflectUtil.getMethods(annotationType)).forEach(method -> {
			LFAliasFor aliasFor = AnnotationUtil.getAnnotation(method, LFAliasFor.class);
			if (ObjectUtil.isNotNull(aliasFor)) {
				aliasMap.put(method.getName(), aliasFor.value());
				defaultValueMap.put(method.getName(), getDefaultValue(annotationType, method.getName()));
			}
		});

		aliasMap.forEach((key, value1) -> {
			Object value = ReflectUtil.invoke(annotation, key);
			Object defaultValue = defaultValueMap.get(key);
			if (ObjectUtil.notEqual(value, defaultValue)) {
				AnnotationUtil.setValue(annotation, value1, value);
			}
		});

		annoCacheMap.put(cacheKey, annotation);

		return annotation;
	
<no_super_class>