Spring AnnotationUtils

  • Author: HuiFer
  • 源码阅读仓库: SourceHot-Spring
  • org.springframework.core.annotation.AnnotationUtils提供了注解相关的方法
    1. getAnnotation: 获取注解
    2. findAnnotation: 寻找注解
    3. getValue: 获取属性值
    4. getDefaultValue: 获取默认值

getAnnotation

  • 测试用例如下
  1. @Test
  2. public void findMethodAnnotationOnLeaf() throws Exception {
  3. Method m = Leaf.class.getMethod("annotatedOnLeaf");
  4. assertNotNull(m.getAnnotation(Order.class));
  5. assertNotNull(getAnnotation(m, Order.class));
  6. assertNotNull(findAnnotation(m, Order.class));
  7. }
  • org.springframework.core.annotation.AnnotationUtils.getAnnotation(java.lang.reflect.Method, java.lang.Class<A>)
  1. /**
  2. * Get a single {@link Annotation} of {@code annotationType} from the
  3. * supplied {@link Method}, where the annotation is either <em>present</em>
  4. * or <em>meta-present</em> on the method.
  5. * <p>Correctly handles bridge {@link Method Methods} generated by the compiler.
  6. * <p>Note that this method supports only a single level of meta-annotations.
  7. * For support for arbitrary levels of meta-annotations, use
  8. * {@link #findAnnotation(Method, Class)} instead.
  9. *
  10. * @param method the method to look for annotations on
  11. * 被检查的函数
  12. * @param annotationType the annotation type to look for
  13. * 需要检测的注解类型
  14. * @return the first matching annotation, or {@code null} if not found
  15. * @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method)
  16. * @see #getAnnotation(AnnotatedElement, Class)
  17. */
  18. @Nullable
  19. public static <A extends Annotation> A getAnnotation(Method method, Class<A> annotationType) {
  20. // 函数
  21. Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method);
  22. // 强制转换
  23. return getAnnotation((AnnotatedElement) resolvedMethod, annotationType);
  24. }
  • method

image-20200116085344737

  • annotationType

image-20200116085423073

  1. @Nullable
  2. public static <A extends Annotation> A getAnnotation(AnnotatedElement annotatedElement, Class<A> annotationType) {
  3. try {
  4. // 获取注解
  5. A annotation = annotatedElement.getAnnotation(annotationType);
  6. if (annotation == null) {
  7. for (Annotation metaAnn : annotatedElement.getAnnotations()) {
  8. annotation = metaAnn.annotationType().getAnnotation(annotationType);
  9. if (annotation != null) {
  10. break;
  11. }
  12. }
  13. }
  14. return (annotation != null ? synthesizeAnnotation(annotation, annotatedElement) : null);
  15. } catch (Throwable ex) {
  16. handleIntrospectionFailure(annotatedElement, ex);
  17. return null;
  18. }
  19. }
  • org.springframework.core.annotation.AnnotationUtils.synthesizeAnnotation(A, java.lang.reflect.AnnotatedElement)
  1. public static <A extends Annotation> A synthesizeAnnotation(
  2. A annotation, @Nullable AnnotatedElement annotatedElement) {
  3. return synthesizeAnnotation(annotation, (Object) annotatedElement);
  4. }
  1. /**
  2. * 注解是否存在别名,没有直接返回
  3. *
  4. * @param annotation 注解
  5. * @param annotatedElement 函数
  6. * @param <A>
  7. * @return
  8. */
  9. @SuppressWarnings("unchecked")
  10. static <A extends Annotation> A synthesizeAnnotation(A annotation, @Nullable Object annotatedElement) {
  11. if (annotation instanceof SynthesizedAnnotation || hasPlainJavaAnnotationsOnly(annotatedElement)) {
  12. return annotation;
  13. }
  14. // 具体的注解
  15. Class<? extends Annotation> annotationType = annotation.annotationType();
  16. if (!isSynthesizable(annotationType)) {
  17. return annotation;
  18. }
  19. DefaultAnnotationAttributeExtractor attributeExtractor =
  20. new DefaultAnnotationAttributeExtractor(annotation, annotatedElement);
  21. InvocationHandler handler = new SynthesizedAnnotationInvocationHandler(attributeExtractor);
  22. // Can always expose Spring's SynthesizedAnnotation marker since we explicitly check for a
  23. // synthesizable annotation before (which needs to declare @AliasFor from the same package)
  24. Class<?>[] exposedInterfaces = new Class<?>[]{annotationType, SynthesizedAnnotation.class};
  25. return (A) Proxy.newProxyInstance(annotation.getClass().getClassLoader(), exposedInterfaces, handler);
  26. }

-org.springframework.core.annotation.AnnotationUtils.isSynthesizable

  1. @SuppressWarnings("unchecked")
  2. private static boolean isSynthesizable(Class<? extends Annotation> annotationType) {
  3. if (hasPlainJavaAnnotationsOnly(annotationType)) {
  4. return false;
  5. }
  6. // 从缓存中获取当前注解,不存在null
  7. Boolean synthesizable = synthesizableCache.get(annotationType);
  8. if (synthesizable != null) {
  9. return synthesizable;
  10. }
  11. synthesizable = Boolean.FALSE;
  12. for (Method attribute : getAttributeMethods(annotationType)) {
  13. if (!getAttributeAliasNames(attribute).isEmpty()) {
  14. synthesizable = Boolean.TRUE;
  15. break;
  16. }
  17. // 获取返回值类型
  18. Class<?> returnType = attribute.getReturnType();
  19. // 根据返回值做不同处理
  20. if (Annotation[].class.isAssignableFrom(returnType)) {
  21. Class<? extends Annotation> nestedAnnotationType =
  22. (Class<? extends Annotation>) returnType.getComponentType();
  23. if (isSynthesizable(nestedAnnotationType)) {
  24. synthesizable = Boolean.TRUE;
  25. break;
  26. }
  27. } else if (Annotation.class.isAssignableFrom(returnType)) {
  28. Class<? extends Annotation> nestedAnnotationType = (Class<? extends Annotation>) returnType;
  29. if (isSynthesizable(nestedAnnotationType)) {
  30. synthesizable = Boolean.TRUE;
  31. break;
  32. }
  33. }
  34. }
  35. synthesizableCache.put(annotationType, synthesizable);
  36. return synthesizable;
  37. }
  • org.springframework.core.annotation.AnnotationUtils#getAttributeMethods
  1. static List<Method> getAttributeMethods(Class<? extends Annotation> annotationType) {
  2. List<Method> methods = attributeMethodsCache.get(annotationType);
  3. if (methods != null) {
  4. return methods;
  5. }
  6. methods = new ArrayList<>();
  7. // annotationType.getDeclaredMethods() 获取注解中的方法
  8. for (Method method : annotationType.getDeclaredMethods()) {
  9. if (isAttributeMethod(method)) {
  10. ReflectionUtils.makeAccessible(method);
  11. methods.add(method);
  12. }
  13. }
  14. // 缓存 key:注解,value:函数列表
  15. attributeMethodsCache.put(annotationType, methods);
  16. // 函数列表
  17. return methods;
  18. }
  • org.springframework.core.annotation.AnnotationUtils#isAttributeMethod
  1. /**
  2. * Determine if the supplied {@code method} is an annotation attribute method.
  3. * <p>
  4. * 做3个判断
  5. * <ol>
  6. * <li>函数不为空(method != null)</li>
  7. * <li>参数列表是不是空(method.getParameterCount() == 0)</li>
  8. * <li>返回类型不是void(method.getReturnType() != void.class)</li>
  9. * </ol>
  10. *
  11. * @param method the method to check
  12. * @return {@code true} if the method is an attribute method
  13. * @since 4.2
  14. */
  15. static boolean isAttributeMethod(@Nullable Method method) {
  16. return (method != null && method.getParameterCount() == 0 && method.getReturnType() !=void.class);
  17. }
  • org.springframework.util.ReflectionUtils#makeAccessible(java.lang.reflect.Method)
  1. @SuppressWarnings("deprecation") // on JDK 9
  2. public static void makeAccessible(Method method) {
  3. // 1. 方法修饰符是不是public
  4. // 2. 注解是不是public
  5. // 3. 是否重写
  6. if ((!Modifier.isPublic(method.getModifiers()) ||
  7. !Modifier.isPublic(method.getDeclaringClass().getModifiers())) && !method.isAccessible()) {
  8. method.setAccessible(true);
  9. }
  10. }

处理结果

image-20200116085726577

image-20200116085737632

处理结果和 Order 定义相同

  1. @Retention(RetentionPolicy.RUNTIME)
  2. @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
  3. @Documented
  4. public @interface Order {
  5. /**
  6. * The order value.
  7. * <p>Default is {@link Ordered#LOWEST_PRECEDENCE}.
  8. *
  9. * 启动顺序,默认integer最大值
  10. * @see Ordered#getOrder()
  11. */
  12. int value() default Ordered.LOWEST_PRECEDENCE;
  13. }

最终返回

image-20200116085927359

findAnnotation

  • org.springframework.core.annotation.AnnotationUtils#findAnnotation(java.lang.reflect.Method, java.lang.Class<A>)
  1. @SuppressWarnings("unchecked")
  2. @Nullable
  3. public static <A extends Annotation> A findAnnotation(Method method, @Nullable Class<A> annotationType) {
  4. Assert.notNull(method, "Method must not be null");
  5. if (annotationType == null) {
  6. return null;
  7. }
  8. // 创建注解缓存,key:被扫描的函数,value:注解
  9. AnnotationCacheKey cacheKey = new AnnotationCacheKey(method, annotationType);
  10. // 从findAnnotationCache获取缓存
  11. A result = (A) findAnnotationCache.get(cacheKey);
  12. if (result == null) {
  13. Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method);
  14. // 寻找注解
  15. result = findAnnotation((AnnotatedElement) resolvedMethod, annotationType);
  16. if (result == null) {
  17. result = searchOnInterfaces(method, annotationType, method.getDeclaringClass().getInterfaces());
  18. }
  19. Class<?> clazz = method.getDeclaringClass();
  20. while (result == null) {
  21. clazz = clazz.getSuperclass();
  22. if (clazz == null || clazz == Object.class) {
  23. break;
  24. }
  25. Set<Method> annotatedMethods = getAnnotatedMethodsInBaseType(clazz);
  26. if (!annotatedMethods.isEmpty()) {
  27. for (Method annotatedMethod : annotatedMethods) {
  28. if (isOverride(method, annotatedMethod)) {
  29. Method resolvedSuperMethod = BridgeMethodResolver.findBridgedMethod(annotatedMethod);
  30. result = findAnnotation((AnnotatedElement) resolvedSuperMethod, annotationType);
  31. if (result != null) {
  32. break;
  33. }
  34. }
  35. }
  36. }
  37. if (result == null) {
  38. result = searchOnInterfaces(method, annotationType, clazz.getInterfaces());
  39. }
  40. }
  41. if (result != null) {
  42. // 处理注解
  43. result = synthesizeAnnotation(result, method);
  44. // 添加缓存
  45. findAnnotationCache.put(cacheKey, result);
  46. }
  47. }
  48. // 返回
  49. return result;
  50. }
  • org.springframework.core.annotation.AnnotationUtils.AnnotationCacheKey
  1. private static final class AnnotationCacheKey implements Comparable<AnnotationCacheKey> {
  2. /**
  3. * 带有注解的函数或者类
  4. */
  5. private final AnnotatedElement element;
  6. /**
  7. * 注解
  8. */
  9. private final Class<? extends Annotation> annotationType;
  10. public AnnotationCacheKey(AnnotatedElement element, Class<? extends Annotation> annotationType) {
  11. this.element = element;
  12. this.annotationType = annotationType;
  13. }
  14. }
  • org.springframework.core.annotation.AnnotationUtils#findAnnotation(java.lang.reflect.AnnotatedElement, java.lang.Class<A>)
  1. @Nullable
  2. public static <A extends Annotation> A findAnnotation(
  3. AnnotatedElement annotatedElement, @Nullable Class<A> annotationType) {
  4. // 注解类型不为空
  5. if (annotationType == null) {
  6. return null;
  7. }
  8. // Do NOT store result in the findAnnotationCache since doing so could break
  9. // findAnnotation(Class, Class) and findAnnotation(Method, Class).
  10. // 寻找注解
  11. A ann = findAnnotation(annotatedElement, annotationType, new HashSet<>());
  12. return (ann != null ? synthesizeAnnotation(ann, annotatedElement) : null);
  13. }
  • org.springframework.core.annotation.AnnotationUtils#findAnnotation(java.lang.reflect.AnnotatedElement, java.lang.Class<A>, java.util.Set<java.lang.annotation.Annotation>)
  1. @Nullable
  2. private static <A extends Annotation> A findAnnotation(
  3. AnnotatedElement annotatedElement, Class<A> annotationType, Set<Annotation> visited) {
  4. try {
  5. // 直接获取注解
  6. A annotation = annotatedElement.getDeclaredAnnotation(annotationType);
  7. if (annotation != null) {
  8. return annotation;
  9. }
  10. // 多级注解
  11. for (Annotation declaredAnn : getDeclaredAnnotations(annotatedElement)) {
  12. Class<? extends Annotation> declaredType = declaredAnn.annotationType();
  13. // 注解是否 由java.lang.annotation提供
  14. if (!isInJavaLangAnnotationPackage(declaredType) && visited.add(declaredAnn)) {
  15. annotation = findAnnotation((AnnotatedElement) declaredType, annotationType, visited);
  16. if (annotation != null) {
  17. return annotation;
  18. }
  19. }
  20. }
  21. } catch (Throwable ex) {
  22. handleIntrospectionFailure(annotatedElement, ex);
  23. }
  24. return null;
  25. }

image-20200116092259944

  • synthesizeAnnotation方法就不再重复一遍了可以看上文

getValue

  • 测试用例
  1. @Test
  2. public void getValueFromAnnotation() throws Exception {
  3. Method method = SimpleFoo.class.getMethod("something", Object.class);
  4. Order order = findAnnotation(method, Order.class);
  5. assertEquals(1, getValue(order, VALUE));
  6. assertEquals(1, getValue(order));
  7. }
  • org.springframework.core.annotation.AnnotationUtils#getValue(java.lang.annotation.Annotation, java.lang.String)
  1. @Nullable
  2. public static Object getValue(@Nullable Annotation annotation, @Nullable String attributeName) {
  3. if (annotation == null || !StringUtils.hasText(attributeName)) {
  4. return null;
  5. }
  6. try {
  7. // 根据attributeName获取注解对应函数
  8. Method method = annotation.annotationType().getDeclaredMethod(attributeName);
  9. ReflectionUtils.makeAccessible(method);
  10. // 反射执行方法
  11. return method.invoke(annotation);
  12. } catch (NoSuchMethodException ex) {
  13. return null;
  14. } catch (InvocationTargetException ex) {
  15. rethrowAnnotationConfigurationException(ex.getTargetException());
  16. throw new IllegalStateException("Could not obtain value for annotation attribute '" +
  17. attributeName + "' in " + annotation, ex);
  18. } catch (Throwable ex) {
  19. handleIntrospectionFailure(annotation.getClass(), ex);
  20. return null;
  21. }
  22. }
  1. @Nullable
  2. public static Object getValue(Annotation annotation) {
  3. return getValue(annotation, VALUE);
  4. }

getDefaultValue

  • org.springframework.core.annotation.AnnotationUtils#getDefaultValue(java.lang.annotation.Annotation)
  1. @Nullable
  2. public static Object getDefaultValue(Annotation annotation) {
  3. return getDefaultValue(annotation, VALUE);
  4. }
  1. @Nullable
  2. public static Object getDefaultValue(
  3. @Nullable Class<? extends Annotation> annotationType, @Nullable String attributeName) {
  4. if (annotationType == null || !StringUtils.hasText(attributeName)) {
  5. return null;
  6. }
  7. try {
  8. // 直接获取defaultValue
  9. return annotationType.getDeclaredMethod(attributeName).getDefaultValue();
  10. } catch (Throwable ex) {
  11. handleIntrospectionFailure(annotationType, ex);
  12. return null;
  13. }
  14. }